
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
  <head>
    <meta charset="utf-8" />
    <title>编程常见问题 &#8212; Python 3.7.8 文档</title>
    <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <script type="text/javascript" src="../_static/translations.js"></script>
    
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="在 Python 3.7.8 文档 中搜索"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="关于这些文档" href="../about.html" />
    <link rel="index" title="索引" href="../genindex.html" />
    <link rel="search" title="搜索" href="../search.html" />
    <link rel="copyright" title="版权所有" href="../copyright.html" />
    <link rel="next" title="设计和历史常见问题" href="design.html" />
    <link rel="prev" title="Python常见问题" href="general.html" />
    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
    <link rel="canonical" href="https://docs.python.org/3/faq/programming.html" />
    
    <script type="text/javascript" src="../_static/copybutton.js"></script>
    
    
    
    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>
 

  </head><body>
  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="design.html" title="设计和历史常见问题"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="general.html" title="Python常见问题"
             accesskey="P">上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <a href="../index.html">3.7.8 Documentation</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python 常见问题</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="programming-faq">
<h1><a class="toc-backref" href="#id2">编程常见问题</a><a class="headerlink" href="#programming-faq" title="永久链接至标题">¶</a></h1>
<div class="contents topic" id="id1">
<p class="topic-title">目录</p>
<ul class="simple">
<li><p><a class="reference internal" href="#programming-faq" id="id2">编程常见问题</a></p>
<ul>
<li><p><a class="reference internal" href="#general-questions" id="id3">一般问题</a></p>
<ul>
<li><p><a class="reference internal" href="#is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc" id="id4">Python 有没有提供断点与单步调试等功能的，源码层次的调试器？</a></p></li>
<li><p><a class="reference internal" href="#is-there-a-tool-to-help-find-bugs-or-perform-static-analysis" id="id5">有没有工具来帮助找寻漏洞或进行静态分析？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-create-a-stand-alone-binary-from-a-python-script" id="id6">我如何能够通过一个 Python 脚本创建一个独立运行的二进制文件？</a></p></li>
<li><p><a class="reference internal" href="#are-there-coding-standards-or-a-style-guide-for-python-programs" id="id7">是否有 Python 程序规范代码标准或风格指南？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#core-language" id="id8">核心语言</a></p>
<ul>
<li><p><a class="reference internal" href="#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value" id="id9">当变量有值时，为什么会出现UnboundLocalError？</a></p></li>
<li><p><a class="reference internal" href="#what-are-the-rules-for-local-and-global-variables-in-python" id="id10">Python中的局部变量和全局变量有哪些规则？</a></p></li>
<li><p><a class="reference internal" href="#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result" id="id11">为什么在具有不同值的循环中定义的lambdas都返回相同的结果？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-share-global-variables-across-modules" id="id12">如何跨模块共享全局变量？</a></p></li>
<li><p><a class="reference internal" href="#what-are-the-best-practices-for-using-import-in-a-module" id="id13">导入模块的“最佳实践”是什么？</a></p></li>
<li><p><a class="reference internal" href="#why-are-default-values-shared-between-objects" id="id14">为什么对象之间会共享默认值？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another" id="id15">如何将可选参数或关键字参数从一个函数传递到另一个函数？</a></p></li>
<li><p><a class="reference internal" href="#what-is-the-difference-between-arguments-and-parameters" id="id16">形参和实参之间有什么区别？</a></p></li>
<li><p><a class="reference internal" href="#why-did-changing-list-y-also-change-list-x" id="id17">为什么更改列表 'y' 也会更改列表 'x'？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-write-a-function-with-output-parameters-call-by-reference" id="id18">如何编写带输出参数的函数（通过引用调用）？</a></p></li>
<li><p><a class="reference internal" href="#how-do-you-make-a-higher-order-function-in-python" id="id19">如何在Python中创建高阶函数？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-copy-an-object-in-python" id="id20">如何在Python中复制对象？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-find-the-methods-or-attributes-of-an-object" id="id21">如何找到对象的方法或属性？</a></p></li>
<li><p><a class="reference internal" href="#how-can-my-code-discover-the-name-of-an-object" id="id22">我的代码如何才能发现对象的名称？</a></p></li>
<li><p><a class="reference internal" href="#what-s-up-with-the-comma-operator-s-precedence" id="id23">逗号运算符的优先级是什么？</a></p></li>
<li><p><a class="reference internal" href="#is-there-an-equivalent-of-c-s-ternary-operator" id="id24">是否有与 C 的 &quot;?:&quot; 三目运算符等价的东西？</a></p></li>
<li><p><a class="reference internal" href="#is-it-possible-to-write-obfuscated-one-liners-in-python" id="id25">是否可以用Python编写混淆的单行程序?</a></p></li>
<li><p><a class="reference internal" href="#what-does-the-slash-in-the-parameter-list-of-a-function-mean" id="id26">函数参数列表中的斜杠（/）是什么意思？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#numbers-and-strings" id="id27">数字和字符串</a></p>
<ul>
<li><p><a class="reference internal" href="#how-do-i-specify-hexadecimal-and-octal-integers" id="id28">如何指定十六进制和八进制整数？</a></p></li>
<li><p><a class="reference internal" href="#why-does-22-10-return-3" id="id29">为什么-22 // 10返回-3？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-convert-a-string-to-a-number" id="id30">如何将字符串转换为数字？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-convert-a-number-to-a-string" id="id31">如何将数字转换为字符串？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-modify-a-string-in-place" id="id32">如何修改字符串？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-use-strings-to-call-functions-methods" id="id33">如何使用字符串调用函数/方法？</a></p></li>
<li><p><a class="reference internal" href="#is-there-an-equivalent-to-perl-s-chomp-for-removing-trailing-newlines-from-strings" id="id34">是否有与Perl 的chomp() 等效的方法，用于从字符串中删除尾随换行符？</a></p></li>
<li><p><a class="reference internal" href="#is-there-a-scanf-or-sscanf-equivalent" id="id35">是否有 scanf() 或 sscanf() 的对应物？</a></p></li>
<li><p><a class="reference internal" href="#what-does-unicodedecodeerror-or-unicodeencodeerror-error-mean" id="id36">'UnicodeDecodeError' 或 'UnicodeEncodeError' 错误是什么意思？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#performance" id="id37">性能</a></p>
<ul>
<li><p><a class="reference internal" href="#my-program-is-too-slow-how-do-i-speed-it-up" id="id38">我的程序太慢了。该如何加快速度？</a></p></li>
<li><p><a class="reference internal" href="#what-is-the-most-efficient-way-to-concatenate-many-strings-together" id="id39">将多个字符串连接在一起的最有效方法是什么？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#sequences-tuples-lists" id="id40">序列（元组/列表）</a></p>
<ul>
<li><p><a class="reference internal" href="#how-do-i-convert-between-tuples-and-lists" id="id41">如何在元组和列表之间进行转换？</a></p></li>
<li><p><a class="reference internal" href="#what-s-a-negative-index" id="id42">什么是负数序号？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-iterate-over-a-sequence-in-reverse-order" id="id43">如何以相反的顺序迭代序列？</a></p></li>
<li><p><a class="reference internal" href="#how-do-you-remove-duplicates-from-a-list" id="id44">如何从列表中删除重复项？</a></p></li>
<li><p><a class="reference internal" href="#how-do-you-make-an-array-in-python" id="id45">如何在Python中创建数组？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-create-a-multidimensional-list" id="id46">如何创建多维列表？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-apply-a-method-to-a-sequence-of-objects" id="id47">如何将方法应用于一系列对象？</a></p></li>
<li><p><a class="reference internal" href="#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works" id="id48">为什么 a_tuple[i] += ['item'] 会在执行加法时引发异常？</a></p></li>
<li><p><a class="reference internal" href="#i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python" id="id49">我想做一个复杂的排序：你能用Python做一个Schwartzian变换吗？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-sort-one-list-by-values-from-another-list" id="id50">如何按其他列表中的值对一个列表进行排序？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#objects" id="id51">对象</a></p>
<ul>
<li><p><a class="reference internal" href="#what-is-a-class" id="id52">什么是类？</a></p></li>
<li><p><a class="reference internal" href="#what-is-a-method" id="id53">什么是方法？</a></p></li>
<li><p><a class="reference internal" href="#what-is-self" id="id54">什么是 self ？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it" id="id55">如何检查对象是否为给定类或其子类的一个实例？</a></p></li>
<li><p><a class="reference internal" href="#what-is-delegation" id="id56">什么是委托？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-call-a-method-defined-in-a-base-class-from-a-derived-class-that-overrides-it" id="id57">如何从覆盖基类的派生类调用基类中定义的方法?</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class" id="id58">如何组织代码以便更改基类？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-create-static-class-data-and-static-class-methods" id="id59">如何创建静态类数据和静态类方法？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-overload-constructors-or-methods-in-python" id="id60">如何在Python中重载构造函数（或方法）？</a></p></li>
<li><p><a class="reference internal" href="#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam" id="id61">我尝试使用 __spam ，但是得到一个关于 _SomeClassName__spam 的错误信息。</a></p></li>
<li><p><a class="reference internal" href="#my-class-defines-del-but-it-is-not-called-when-i-delete-the-object" id="id62">类定义了 __del__ 方法，但是删除对象时没有调用它。</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-get-a-list-of-all-instances-of-a-given-class" id="id63">如何获取给定类的所有实例的列表？</a></p></li>
<li><p><a class="reference internal" href="#why-does-the-result-of-id-appear-to-be-not-unique" id="id64">为什么 <code class="docutils literal notranslate"><span class="pre">id()</span></code> 的结果看起来不是唯一的？</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#modules" id="id65">模块</a></p>
<ul>
<li><p><a class="reference internal" href="#how-do-i-create-a-pyc-file" id="id66">如何创建 .pyc 文件？</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-find-the-current-module-name" id="id67">如何找到当前模块名称？</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-have-modules-that-mutually-import-each-other" id="id68">如何让模块相互导入？</a></p></li>
<li><p><a class="reference internal" href="#import-x-y-z-returns-module-x-how-do-i-get-z" id="id69">__import__('x.y.z') 返回 &lt;module 'x'&gt;; 如何获取z?</a></p></li>
<li><p><a class="reference internal" href="#when-i-edit-an-imported-module-and-reimport-it-the-changes-don-t-show-up-why-does-this-happen" id="id70">当我编辑了导入过的模块并重新导入它时，这些变化没有显示出来。为什么会这样？</a></p></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="general-questions">
<h2><a class="toc-backref" href="#id3">一般问题</a><a class="headerlink" href="#general-questions" title="永久链接至标题">¶</a></h2>
<div class="section" id="is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc">
<h3><a class="toc-backref" href="#id4">Python 有没有提供断点与单步调试等功能的，源码层次的调试器？</a><a class="headerlink" href="#is-there-a-source-code-level-debugger-with-breakpoints-single-stepping-etc" title="永久链接至标题">¶</a></h3>
<p>有的。</p>
<p>以下介绍了一些 Python 的调试器，内置函数 <a class="reference internal" href="../library/functions.html#breakpoint" title="breakpoint"><code class="xref py py-func docutils literal notranslate"><span class="pre">breakpoint()</span></code></a> 允许你使用其中的任何一种。</p>
<p>pdb 模块是一个简单但是够用的控制台模式 Python 调试器。 它是标准 Python 库的一部分，并且 <a class="reference internal" href="../library/pdb.html#module-pdb" title="pdb: The Python debugger for interactive interpreters."><code class="xref py py-mod docutils literal notranslate"><span class="pre">已收录于库参考手册</span></code></a>。 你也可以通过使用 pdb 代码作为样例来编写你自己的调试器。</p>
<p>作为标准 Python 发行版附带组件的 IDLE 交互式环境（通常位于 Tools/scripts/idle）中包含一个图形化的调试器。</p>
<p>PythonWin 是一个包含有基于 pdb 的 GUI 调试器的 Python IDE。 Pythonwin 调试器会为断点加上颜色，并具有许多很棒的特性，例如也可以非 Pythonwin 程序。 Pythonwin 是 <a class="reference external" href="https://sourceforge.net/projects/pywin32/">Python for Windows Extensions</a> 项目的一部分，也是 ActivePython 发行版的一部分（参见 <a class="reference external" href="https://www.activestate.com/activepython">https://www.activestate.com/activepython</a>）。</p>
<p><a class="reference external" href="http://boa-constructor.sourceforge.net/">Boa Constructor</a> 是一个使用wxWidgets的IDE和GUI构建器。它提供可视化框架创建和操作，对象检查器，源对象浏览器上的许多视图，继承层次结构，doc字符串生成的html文档，高级调试器，集成帮助和Zope支持。</p>
<p><a class="reference external" href="http://eric-ide.python-projects.org/">Eric</a> 是一个基于PyQt和Scintilla编辑组件构建的IDE。</p>
<p>Pydb是标准Python调试器pdb的一个版本，经过修改后可与DDD（数据显示调试器）一起使用，DDD是一种流行的图形化调试器前端。 Pydb可以在 <a class="reference external" href="http://bashdb.sourceforge.net/pydb/">http://bashdb.sourceforge.net/pydb/</a> 找到，DDD可以在 <a class="reference external" href="https://www.gnu.org/software/ddd">https://www.gnu.org/software/ddd</a> 找到。</p>
<p>有许多商业Python IDE包括图形调试器。他们包括：</p>
<ul class="simple">
<li><p>Wing IDE (<a class="reference external" href="https://wingware.com/">https://wingware.com/</a>)</p></li>
<li><p>Komodo IDE (<a class="reference external" href="https://komodoide.com/">https://komodoide.com/</a>)</p></li>
<li><p>PyCharm (<a class="reference external" href="https://www.jetbrains.com/pycharm/">https://www.jetbrains.com/pycharm/</a>)</p></li>
</ul>
</div>
<div class="section" id="is-there-a-tool-to-help-find-bugs-or-perform-static-analysis">
<h3><a class="toc-backref" href="#id5">有没有工具来帮助找寻漏洞或进行静态分析？</a><a class="headerlink" href="#is-there-a-tool-to-help-find-bugs-or-perform-static-analysis" title="永久链接至标题">¶</a></h3>
<p>有的。</p>
<p>PyChecker 是一个寻找Python代码漏洞以及对代码复杂性和风格给出警告的工具。你可以从这里获得PyChecker: <a class="reference external" href="http://pychecker.sourceforge.net/">http://pychecker.sourceforge.net/</a> 。</p>
<p><a class="reference external" href="https://www.pylint.org/">Pylint</a> 是另一个检查模块是否满足编码标准的工具，也可以编写插件来添加自定义功能。除了PyChecker 执行的错误检查之外， Pylint 还提供了一些额外的功能，例如检查行长度，变量名称是否根据您的编码标准格式良好，声明的接口是否完全实现等等。 <a class="reference external" href="https://docs.pylint.org/">https://docs.pylint.org/</a> 提供了Pylint功能的完整列表。</p>
<p>静态类型检查器，例如 <a class="reference external" href="http://mypy-lang.org/">Mypy</a> 、 <a class="reference external" href="https://pyre-check.org/">Pyre</a> 和 <a class="reference external" href="https://github.com/google/pytype">Pytype</a> 可以检查Python源代码中的类型提示。</p>
</div>
<div class="section" id="how-can-i-create-a-stand-alone-binary-from-a-python-script">
<h3><a class="toc-backref" href="#id6">我如何能够通过一个 Python 脚本创建一个独立运行的二进制文件？</a><a class="headerlink" href="#how-can-i-create-a-stand-alone-binary-from-a-python-script" title="永久链接至标题">¶</a></h3>
<p>如果你想要的只是一个独立的程序，用户可以下载和运行而不必先安装Python发行版，你就不需要将Python编译成C代码。有许多工具可以确定程序所需的模块集，并将这些模块与Python二进制文件绑定在一起以生成单个可执行文件。</p>
<p>一种是使用冻结工具，它包含在Python源代码树 <code class="docutils literal notranslate"><span class="pre">Tools/freeze</span></code> 中。它将Python字节代码转换为C数组；一个C编译器，你可以将所有模块嵌入到一个新程序中，然后将其与标准Python模块链接。</p>
<p>它的工作原理是递归扫描源代码以获取import语句（两种形式），并在标准Python路径和源目录（用于内置模块）中查找模块。 然后，它将用Python编写的模块的字节码转换为C代码（可以使用编组模块转换为代码对象的数组初始化器），并创建一个定制的配置文件，该文件仅包含程序中实际使用的内置模块。 然后，它编译生成的C代码并将其与Python解释器的其余部分链接，以形成一个独立的二进制文件，其行为与你的脚本完全相同。</p>
<p>显然， freeze 需要一个C编译器。有几个其他实用工具不需要。 一个是Thomas Heller的py2exe（仅限Windows）</p>
<blockquote>
<div><p><a class="reference external" href="http://www.py2exe.org/">http://www.py2exe.org/</a></p>
</div></blockquote>
<p>另一个工具是 Anthony Tuininga 的 <a class="reference external" href="https://anthony-tuininga.github.io/cx_Freeze/">cx_Freeze</a>。</p>
</div>
<div class="section" id="are-there-coding-standards-or-a-style-guide-for-python-programs">
<h3><a class="toc-backref" href="#id7">是否有 Python 程序规范代码标准或风格指南？</a><a class="headerlink" href="#are-there-coding-standards-or-a-style-guide-for-python-programs" title="永久链接至标题">¶</a></h3>
<p>有的。 请参阅标准库模块所要求的代码风格描述文档 <span class="target" id="index-9"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0008"><strong>PEP 8</strong></a> 。</p>
</div>
</div>
<div class="section" id="core-language">
<h2><a class="toc-backref" href="#id8">核心语言</a><a class="headerlink" href="#core-language" title="永久链接至标题">¶</a></h2>
<div class="section" id="why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value">
<h3><a class="toc-backref" href="#id9">当变量有值时，为什么会出现UnboundLocalError？</a><a class="headerlink" href="#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value" title="永久链接至标题">¶</a></h3>
<p>通过在函数体中的某处添加赋值语句，导致以前正常工作的代码被修改而得到 UnboundLocalError 会令人感到意外。</p>
<p>以下代码：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">bar</span><span class="p">():</span>
<span class="gp">... </span>    <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">bar</span><span class="p">()</span>
<span class="go">10</span>
</pre></div>
</div>
<p>正常工作，但是以下代码</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="gp">... </span>    <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="gp">... </span>    <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>会得到一个 UnboundLocalError ：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">foo</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
  <span class="c">...</span>
<span class="gr">UnboundLocalError</span>: <span class="n">local variable &#39;x&#39; referenced before assignment</span>
</pre></div>
</div>
<p>这是因为当你对作用域中的变量进行赋值时，该变量将成为该作用域的局部变量，并在外部作用域中隐藏任何类似命名的变量。由于foo中的最后一个语句为 <code class="docutils literal notranslate"><span class="pre">x</span></code> 分配了一个新值，编译器会将其识别为局部变量。因此，当先前的 <code class="docutils literal notranslate"><span class="pre">print(x)</span></code> 尝试打印未初始化的局部变量时会导致错误。</p>
<p>在上面的示例中，你可以通过将其声明为全局来访问外部作用域变量：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">foobar</span><span class="p">():</span>
<span class="gp">... </span>    <span class="k">global</span> <span class="n">x</span>
<span class="gp">... </span>    <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="gp">... </span>    <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">foobar</span><span class="p">()</span>
<span class="go">10</span>
</pre></div>
</div>
<p>这个显式声明是必需的，以便提醒你（与类和实例变量的表面类似情况不同），你实际上是在外部作用域中修改变量的值</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="go">11</span>
</pre></div>
</div>
<p>你可以使用 <a class="reference internal" href="../reference/simple_stmts.html#nonlocal"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">nonlocal</span></code></a> 关键字在嵌套作用域中执行类似的操作：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="gp">... </span>   <span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="gp">... </span>   <span class="k">def</span> <span class="nf">bar</span><span class="p">():</span>
<span class="gp">... </span>       <span class="k">nonlocal</span> <span class="n">x</span>
<span class="gp">... </span>       <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="gp">... </span>       <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="gp">... </span>   <span class="n">bar</span><span class="p">()</span>
<span class="gp">... </span>   <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">foo</span><span class="p">()</span>
<span class="go">10</span>
<span class="go">11</span>
</pre></div>
</div>
</div>
<div class="section" id="what-are-the-rules-for-local-and-global-variables-in-python">
<h3><a class="toc-backref" href="#id10">Python中的局部变量和全局变量有哪些规则？</a><a class="headerlink" href="#what-are-the-rules-for-local-and-global-variables-in-python" title="永久链接至标题">¶</a></h3>
<p>在Python中，仅在函数内引用的变量是隐式全局变量。如果在函数体内的任何位置为变量赋值，则除非明确声明为全局，否则将其视为局部值。</p>
<p>虽然起初有点令人惊讶，但片刻考虑就可以解释。一方面，要求 <a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> 表示已分配的变量可以防止意外的副作用。另一方面，如果所有全局引用都需要 <code class="docutils literal notranslate"><span class="pre">global</span></code> ，那么你一直都在使用 <code class="docutils literal notranslate"><span class="pre">global</span></code> 。你必须将对内置函数或导入模块的组件的每个引用声明为全局。这种杂乱会破坏 <code class="docutils literal notranslate"><span class="pre">global</span></code> 声明用于识别副作用的有用性。</p>
</div>
<div class="section" id="why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result">
<h3><a class="toc-backref" href="#id11">为什么在具有不同值的循环中定义的lambdas都返回相同的结果？</a><a class="headerlink" href="#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result" title="永久链接至标题">¶</a></h3>
<p>假设你使用for循环来定义几个不同的 lambda （甚至是普通函数），例如：:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="gp">... </span>    <span class="n">squares</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<p>这给你一个包含5个lambdas的列表，它们计算 <code class="docutils literal notranslate"><span class="pre">x**2</span></code> 。你可能会期望，当它们被调用时，它们将分别返回 <code class="docutils literal notranslate"><span class="pre">0</span></code> 、 <code class="docutils literal notranslate"><span class="pre">1</span></code> 、 <code class="docutils literal notranslate"><span class="pre">4</span></code> 、 <code class="docutils literal notranslate"><span class="pre">9</span></code> 和 <code class="docutils literal notranslate"><span class="pre">16</span></code> 。但是，当你真正尝试时，你会看到它们都返回 <code class="docutils literal notranslate"><span class="pre">16</span></code> 。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span><span class="p">[</span><span class="mi">2</span><span class="p">]()</span>
<span class="go">16</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span><span class="p">[</span><span class="mi">4</span><span class="p">]()</span>
<span class="go">16</span>
</pre></div>
</div>
<p>发生这种情况是因为 <code class="docutils literal notranslate"><span class="pre">x</span></code> 不是lambdas的内部变量，而是在外部作用域中定义，并且在调用lambda时访问它 - 而不是在定义它时。 在循环结束时， <code class="docutils literal notranslate"><span class="pre">x</span></code> 的值是 <code class="docutils literal notranslate"><span class="pre">4</span></code> ，所以所有的函数现在返回 <code class="docutils literal notranslate"><span class="pre">4**2</span></code> ，即 <code class="docutils literal notranslate"><span class="pre">16</span></code> 。你还可以通过更改 <code class="docutils literal notranslate"><span class="pre">x</span></code> 的值来验证这一点，并查看lambdas的结果如何变化:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">8</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span><span class="p">[</span><span class="mi">2</span><span class="p">]()</span>
<span class="go">64</span>
</pre></div>
</div>
<p>为了避免这种情况，你需要将值保存在lambdas的局部变量中，这样它们就不依赖于全局``x`` 的值</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="gp">... </span>    <span class="n">squares</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="k">lambda</span> <span class="n">n</span><span class="o">=</span><span class="n">x</span><span class="p">:</span> <span class="n">n</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<p>这里， <code class="docutils literal notranslate"><span class="pre">n=x</span></code> 在lambda本地创建一个新的变量 <code class="docutils literal notranslate"><span class="pre">n</span></code> ，并在定义lambda时计算，使它具有与 <code class="docutils literal notranslate"><span class="pre">x</span></code> 在循环中该点相同的值。这意味着 <code class="docutils literal notranslate"><span class="pre">n</span></code> 的值在第一个lambda中为 <code class="docutils literal notranslate"><span class="pre">0</span></code> ，在第二个lambda中为 <code class="docutils literal notranslate"><span class="pre">1</span></code> ，在第三个中为 <code class="docutils literal notranslate"><span class="pre">2</span></code> ，依此类推。因此每个lambda现在将返回正确的结果:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span><span class="p">[</span><span class="mi">2</span><span class="p">]()</span>
<span class="go">4</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">squares</span><span class="p">[</span><span class="mi">4</span><span class="p">]()</span>
<span class="go">16</span>
</pre></div>
</div>
<p>请注意，这种行为并不是lambda所特有的，但也适用于常规函数。</p>
</div>
<div class="section" id="how-do-i-share-global-variables-across-modules">
<h3><a class="toc-backref" href="#id12">如何跨模块共享全局变量？</a><a class="headerlink" href="#how-do-i-share-global-variables-across-modules" title="永久链接至标题">¶</a></h3>
<p>在单个程序中跨模块共享信息的规范方法是创建一个特殊模块（通常称为config或cfg）。只需在应用程序的所有模块中导入配置模块；然后该模块可用作全局名称。因为每个模块只有一个实例，所以对模块对象所做的任何更改都会在任何地方反映出来。 例如：</p>
<p>config.py:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>   <span class="c1"># Default value of the &#39;x&#39; configuration setting</span>
</pre></div>
</div>
<p>mod.py:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">config</span>
<span class="n">config</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>main.py:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">config</span>
<span class="kn">import</span> <span class="nn">mod</span>
<span class="nb">print</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">x</span><span class="p">)</span>
</pre></div>
</div>
<p>请注意，出于同样的原因，使用模块也是实现Singleton设计模式的基础。</p>
</div>
<div class="section" id="what-are-the-best-practices-for-using-import-in-a-module">
<h3><a class="toc-backref" href="#id13">导入模块的“最佳实践”是什么？</a><a class="headerlink" href="#what-are-the-best-practices-for-using-import-in-a-module" title="永久链接至标题">¶</a></h3>
<p>通常，不要使用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">modulename</span> <span class="pre">import</span> <span class="pre">*</span></code> 。这样做会使导入器的命名空间变得混乱，并且使得连接器更难以检测未定义的名称。</p>
<p>在文件的顶部导入模块。这样做可以清楚地了解代码所需的其他模块，并避免了模块名称是否在范围内的问题。每行导入一个模块可以轻松添加和删除导入的模块，但每行导入多个模块会占用更少的屏幕空间。</p>
<p>如果按以下顺序导入模块，这是一种很好的做法：</p>
<ol class="arabic simple">
<li><p>标准库模块 -- 例如： <code class="docutils literal notranslate"><span class="pre">sys</span></code>, <code class="docutils literal notranslate"><span class="pre">os</span></code>, <code class="docutils literal notranslate"><span class="pre">getopt</span></code>, <code class="docutils literal notranslate"><span class="pre">re</span></code></p></li>
<li><p>第三方库模块（安装在Python的site-packages目录中的任何内容） --  例如mx.DateTime，ZODB，PIL.Image等</p></li>
<li><p>本地开发的模块</p></li>
</ol>
<p>有时需要将模块导入语句移动到函数或类里面，以避免循环导入问题。Gordon McMillan 说：</p>
<blockquote>
<div><p>当两个模块都使用  &quot;import &lt;module&gt;&quot; 的导入形式时，循环导入就可以了。但是当第 2 个模块想从第 1 个模块中获取一个名称 (&quot;from module import name&quot;) 并且导入位于顶层时，就会出错。 这是因为第 1 个模块中的名称还不可用，因为第 1 个模块正在忙着导入第 2 个模块。</p>
</div></blockquote>
<p>在这种情况下，如果第二个模块仅用于一个函数，则可以轻松地将模块导入语句移动到该函数中。调用导入时，第一个模块将完成初始化，第二个模块可以进行导入。</p>
<p>如果某些模块是特定于平台的，则可能还需要将模块导入语句移出顶级代码。在这种情况下，甚至可能无法导入文件顶部的所有模块。在这种情况下，在相应的特定于平台的代码中导入正确的模块是一个很好的选择。</p>
<p>只有当需要解决诸如避免循环导入或试图减少模块初始化时间的问题时，才可以将导入移动到本地范围，例如在函数定义中。如果根据程序的执行方式，许多导入是不必要的，这种技术尤其有用。如果仅在某个函数中使用模块，您还可能希望将导入移到该函数中。请注意，第一次加载模块可能会因为模块的一次初始化而代价高昂，但多次加载模块实际上是免费的，只需进行几次字典查找。即使模块名称超出了作用域，模块也可能在 <a class="reference internal" href="../library/sys.html#sys.modules" title="sys.modules"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.modules</span></code></a> 中可用。</p>
</div>
<div class="section" id="why-are-default-values-shared-between-objects">
<h3><a class="toc-backref" href="#id14">为什么对象之间会共享默认值？</a><a class="headerlink" href="#why-are-default-values-shared-between-objects" title="永久链接至标题">¶</a></h3>
<p>这种类型的缺陷通常会惹恼新手程序员。考虑这个函数</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">mydict</span><span class="o">=</span><span class="p">{}):</span>  <span class="c1"># Danger: shared reference to one dict for all calls</span>
    <span class="o">...</span> <span class="n">compute</span> <span class="n">something</span> <span class="o">...</span>
    <span class="n">mydict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
    <span class="k">return</span> <span class="n">mydict</span>
</pre></div>
</div>
<p>第一次调用此函数时，<code class="docutils literal notranslate"><span class="pre">mydict</span></code> 包含一项。第二次，<code class="docutils literal notranslate"><span class="pre">mydict</span></code> 包含两项，因为当 <code class="docutils literal notranslate"><span class="pre">foo()</span></code> 开始执行时， <code class="docutils literal notranslate"><span class="pre">mydict</span></code> 中已经有一项了。</p>
<p>函数调用经常被期望为默认值创建新的对象。 但实际情况并非如此。 默认值会在函数定义时一次性地创建。 如果对象发生改变，就如本示例中的字典那样，则对函数的后续调用将会引用这个被改变的对象。</p>
<p>按照定义，不可变对象例如数字、字符串、元组和 <code class="docutils literal notranslate"><span class="pre">None</span></code> 因为不可变所以是安全的。 对可变对象例如字典、列表和类实例的改变则可能造成迷惑。</p>
<p>由于这一特性，在编程中应遵循的一项好习惯是不使用可变对象作为默认值。 而应使用 <code class="docutils literal notranslate"><span class="pre">None</span></code> 作为默认值和函数中的值，检查值为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 的形参并创建相应的列表、字典或其他可变对象。 例如，不要这样写:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">mydict</span><span class="o">=</span><span class="p">{}):</span>
    <span class="o">...</span>
</pre></div>
</div>
<p>而要这样写:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">mydict</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">mydict</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">mydict</span> <span class="o">=</span> <span class="p">{}</span>  <span class="c1"># create a new dict for local namespace</span>
</pre></div>
</div>
<p>这一特性有时会很有用处。 当你有一个需要进行大量耗时计算的函数时，一个常见技巧是将每次调用函数的参数和结果值缓存起来，并在同样的值被再次请求时返回缓存的值。 这称为“记忆”，具体实现方式可以是这样的:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Callers can only provide two parameters and optionally pass _cache by keyword</span>
<span class="k">def</span> <span class="nf">expensive</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">_cache</span><span class="o">=</span><span class="p">{}):</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_cache</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">_cache</span><span class="p">[(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">)]</span>

    <span class="c1"># Calculate the value</span>
    <span class="n">result</span> <span class="o">=</span> <span class="o">...</span> <span class="n">expensive</span> <span class="n">computation</span> <span class="o">...</span>
    <span class="n">_cache</span><span class="p">[(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">)]</span> <span class="o">=</span> <span class="n">result</span>           <span class="c1"># Store result in the cache</span>
    <span class="k">return</span> <span class="n">result</span>
</pre></div>
</div>
<p>你也可以使用包含一个字典的全局变量而不使用参数默认值；这完全取决于个人偏好。</p>
</div>
<div class="section" id="how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another">
<h3><a class="toc-backref" href="#id15">如何将可选参数或关键字参数从一个函数传递到另一个函数？</a><a class="headerlink" href="#how-can-i-pass-optional-or-keyword-parameters-from-one-function-to-another" title="永久链接至标题">¶</a></h3>
<p>使用函数参数列表中的 <code class="docutils literal notranslate"><span class="pre">*</span></code> 和 <code class="docutils literal notranslate"><span class="pre">**</span></code> 说明符收集参数;这会将位置参数作为元组，将关键字参数作为字典。然后，您可以使用 <code class="docutils literal notranslate"><span class="pre">*</span></code> 和 <code class="docutils literal notranslate"><span class="pre">**</span></code> 调用另一个函数时传递这些参数：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="o">...</span>
    <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;width&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;14.3c&#39;</span>
    <span class="o">...</span>
    <span class="n">g</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="what-is-the-difference-between-arguments-and-parameters">
<span id="faq-argument-vs-parameter"></span><span id="index-1"></span><h3><a class="toc-backref" href="#id16">形参和实参之间有什么区别？</a><a class="headerlink" href="#what-is-the-difference-between-arguments-and-parameters" title="永久链接至标题">¶</a></h3>
<p><a class="reference internal" href="../glossary.html#term-parameter"><span class="xref std std-term">形参</span></a> 是指出现在函数定义中的名称，而 <a class="reference internal" href="../glossary.html#term-argument"><span class="xref std std-term">实参</span></a> 则是在调用函数时实际传入的值。 形参定义了一个函数能接受何种类型的实参。 例如，对于以下函数定义:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">foo</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="k">pass</span>
</pre></div>
</div>
<p><em>foo</em>, <em>bar</em> 和 <em>kwargs</em> 是 <code class="docutils literal notranslate"><span class="pre">func</span></code> 的形参。 但是，在调用 <code class="docutils literal notranslate"><span class="pre">func</span></code> 时，例如：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">func</span><span class="p">(</span><span class="mi">42</span><span class="p">,</span> <span class="n">bar</span><span class="o">=</span><span class="mi">314</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="n">somevar</span><span class="p">)</span>
</pre></div>
</div>
<p>实际的值 <code class="docutils literal notranslate"><span class="pre">42</span></code>, <code class="docutils literal notranslate"><span class="pre">314</span></code> 和 <code class="docutils literal notranslate"><span class="pre">somevar</span></code> 则是实参。</p>
</div>
<div class="section" id="why-did-changing-list-y-also-change-list-x">
<h3><a class="toc-backref" href="#id17">为什么更改列表 'y' 也会更改列表 'x'？</a><a class="headerlink" href="#why-did-changing-list-y-also-change-list-x" title="永久链接至标题">¶</a></h3>
<p>如果你编写的代码就像下面一样：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span> <span class="o">=</span> <span class="n">x</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span>
<span class="go">[10]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span>
<span class="go">[10]</span>
</pre></div>
</div>
<p>你可能想知道为什么追加一个元素也改变了x。</p>
<p>产生这种结果有两个因素：</p>
<ol class="arabic simple">
<li><p>变量只是指向具体对象的名称。 执行 <code class="docutils literal notranslate"><span class="pre">y</span> <span class="pre">=</span> <span class="pre">x</span></code> 并不会为列表创建一个副本 —— 它只是创建了一个新变量 <code class="docutils literal notranslate"><span class="pre">y</span></code> 指向 <code class="docutils literal notranslate"><span class="pre">x</span></code> 所指向的同一对象。 这意味着只存在一个对象（列表），<code class="docutils literal notranslate"><span class="pre">x</span></code> 和 <code class="docutils literal notranslate"><span class="pre">y</span></code> 都是对它的引用。</p></li>
<li><p>列表属于 <a class="reference internal" href="../glossary.html#term-mutable"><span class="xref std std-term">mutable</span></a> 对象，这意味着你可以改变它的内容。</p></li>
</ol>
<p>在调用 <code class="xref py py-meth docutils literal notranslate"><span class="pre">append()</span></code> 之后，这个可变对象的内容由 <code class="docutils literal notranslate"><span class="pre">[]</span></code> 变为 <code class="docutils literal notranslate"><span class="pre">[10]</span></code>。 由于两个变量都指向同一对象，因此使用任何一个名称所访问到的都是修改后的值 <code class="docutils literal notranslate"><span class="pre">[10]</span></code>。</p>
<p>如果我们改为将不可变对象赋值给 <code class="docutils literal notranslate"><span class="pre">x</span></code>:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="mi">5</span>  <span class="c1"># ints are immutable</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span> <span class="o">=</span> <span class="n">x</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span>  <span class="c1"># 5 can&#39;t be mutated, we are creating a new object here</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">x</span>
<span class="go">6</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">y</span>
<span class="go">5</span>
</pre></div>
</div>
<p>我们可以看到在此情况下 <code class="docutils literal notranslate"><span class="pre">x</span></code> 和 <code class="docutils literal notranslate"><span class="pre">y</span></code> 就不再相等了。 这是因为整数是 <a class="reference internal" href="../glossary.html#term-immutable"><span class="xref std std-term">immutable</span></a> 对象，当我们执行 <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">x</span> <span class="pre">+</span> <span class="pre">1</span></code> 时我们并不是改变了 <code class="docutils literal notranslate"><span class="pre">5</span></code> 这个对象的值；而是创建了一个新的对象 (整数 <code class="docutils literal notranslate"><span class="pre">6</span></code>) 并将其赋值给 <code class="docutils literal notranslate"><span class="pre">x</span></code> (也就是改变了 <code class="docutils literal notranslate"><span class="pre">x</span></code> 所指向的对象)。 在赋值之后我们就有了两个对象 (整数 <code class="docutils literal notranslate"><span class="pre">6</span></code> 和 <code class="docutils literal notranslate"><span class="pre">5</span></code>) 以及分别指向它们的两个变量 (<code class="docutils literal notranslate"><span class="pre">x</span></code> 现在指向 <code class="docutils literal notranslate"><span class="pre">6</span></code> 而 <code class="docutils literal notranslate"><span class="pre">y</span></code> 仍然指向 <code class="docutils literal notranslate"><span class="pre">5</span></code>)。</p>
<p>某些操作 (例如 <code class="docutils literal notranslate"><span class="pre">y.append(10)</span></code> 和 <code class="docutils literal notranslate"><span class="pre">y.sort()</span></code>) 是改变原对象，而看上去相似的另一些操作 (例如 <code class="docutils literal notranslate"><span class="pre">y</span> <span class="pre">=</span> <span class="pre">y</span> <span class="pre">+</span> <span class="pre">[10]</span></code> 和 <code class="docutils literal notranslate"><span class="pre">sorted(y)</span></code>) 则是创建新对象。 通常在 Python 中 (以及在标准库的所有代码中) 会改变原对象的方法将返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> 以帮助避免混淆这两种不同类型的操作。 因此如果你错误地使用了 <code class="docutils literal notranslate"><span class="pre">y.sort()</span></code> 并期望它将返回一个经过排序的 <code class="docutils literal notranslate"><span class="pre">y</span></code> 的副本，你得到的结果将会是 <code class="docutils literal notranslate"><span class="pre">None</span></code>，这将导致你的程序产生一个容易诊断的错误。</p>
<p>但是，还存在一类操作，不同的类型执行相同的操作会有不同的行为：那就是增强赋值运算符。 例如，<code class="docutils literal notranslate"><span class="pre">+=</span></code> 会原地改变列表，但不会改变元组或整数 (<code class="docutils literal notranslate"><span class="pre">a_list</span> <span class="pre">+=</span> <span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> 与 <code class="docutils literal notranslate"><span class="pre">a_list.extend([1,</span> <span class="pre">2,</span> <span class="pre">3])</span></code> 一样都会改变 <code class="docutils literal notranslate"><span class="pre">a_list</span></code>，而 <code class="docutils literal notranslate"><span class="pre">some_tuple</span> <span class="pre">+=</span> <span class="pre">(1,</span> <span class="pre">2,</span> <span class="pre">3)</span></code> 和 <code class="docutils literal notranslate"><span class="pre">some_int</span> <span class="pre">+=</span> <span class="pre">1</span></code> 则会创建新的对象)。</p>
<p>换而言之：</p>
<ul class="simple">
<li><p>如果我们有一个可变对象 (<a class="reference internal" href="../library/stdtypes.html#list" title="list"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a>, <a class="reference internal" href="../library/stdtypes.html#dict" title="dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">dict</span></code></a>, <a class="reference internal" href="../library/stdtypes.html#set" title="set"><code class="xref py py-class docutils literal notranslate"><span class="pre">set</span></code></a> 等等)，我们可以使用某些特定的操作来改变它，所有指向它的变量都会显示它的改变。</p></li>
<li><p>如果我们有一个不可变对象 (<a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a>, <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>, <a class="reference internal" href="../library/stdtypes.html#tuple" title="tuple"><code class="xref py py-class docutils literal notranslate"><span class="pre">tuple</span></code></a> 等等)，所有指向它的变量都将显示相同样的值，但凡是会改变这个值的操作将总是返回一个新对象。</p></li>
</ul>
<p>如果你想知道两个变量是否指向相同的对象，你可以使用 <a class="reference internal" href="../reference/expressions.html#is"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">is</span></code></a> 运算符，或内置函数 <a class="reference internal" href="../library/functions.html#id" title="id"><code class="xref py py-func docutils literal notranslate"><span class="pre">id()</span></code></a>。</p>
</div>
<div class="section" id="how-do-i-write-a-function-with-output-parameters-call-by-reference">
<h3><a class="toc-backref" href="#id18">如何编写带输出参数的函数（通过引用调用）？</a><a class="headerlink" href="#how-do-i-write-a-function-with-output-parameters-call-by-reference" title="永久链接至标题">¶</a></h3>
<p>请记住在 Python 中参数是通过赋值来传递的。 由于赋值只是创建了对象的引用，因此在调用者和被调用者的参数名称之间没有别名，所以本身是没有按引用调用的。 你可以通过多种方式实现所需的效果。</p>
<ol class="arabic">
<li><p>通过返回一个结果元组:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">func2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="n">a</span> <span class="o">=</span> <span class="s1">&#39;new-value&#39;</span>        <span class="c1"># a and b are local names</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="mi">1</span>              <span class="c1"># assigned to new objects</span>
    <span class="k">return</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span>            <span class="c1"># return new values</span>

<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="s1">&#39;old-value&#39;</span><span class="p">,</span> <span class="mi">99</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">func2</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>                <span class="c1"># output: new-value 100</span>
</pre></div>
</div>
<p>这几乎总是最清晰明了的解决方案。</p>
</li>
<li><p>通过使用全局变量。 这种方式不是线程安全的，而且也不受推荐。</p></li>
<li><p>通过传递一个可变 (即可原地修改的) 对象:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">func1</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
    <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;new-value&#39;</span>     <span class="c1"># &#39;a&#39; references a mutable list</span>
    <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>        <span class="c1"># changes a shared object</span>

<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;old-value&#39;</span><span class="p">,</span> <span class="mi">99</span><span class="p">]</span>
<span class="n">func1</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>    <span class="c1"># output: new-value 100</span>
</pre></div>
</div>
</li>
<li><p>通过传递一个会被改变的字典:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">func3</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
    <span class="n">args</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;new-value&#39;</span>     <span class="c1"># args is a mutable dictionary</span>
    <span class="n">args</span><span class="p">[</span><span class="s1">&#39;b&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="s1">&#39;b&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>   <span class="c1"># change it in-place</span>

<span class="n">args</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;a&#39;</span><span class="p">:</span> <span class="s1">&#39;old-value&#39;</span><span class="p">,</span> <span class="s1">&#39;b&#39;</span><span class="p">:</span> <span class="mi">99</span><span class="p">}</span>
<span class="n">func3</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s1">&#39;a&#39;</span><span class="p">],</span> <span class="n">args</span><span class="p">[</span><span class="s1">&#39;b&#39;</span><span class="p">])</span>
</pre></div>
</div>
</li>
<li><p>或者在一个类实例中捆绑值:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">callByRef</span><span class="p">:</span>
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">args</span><span class="p">):</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="ow">in</span> <span class="n">args</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">func4</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
    <span class="n">args</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="s1">&#39;new-value&#39;</span>        <span class="c1"># args is a mutable callByRef</span>
    <span class="n">args</span><span class="o">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">b</span> <span class="o">+</span> <span class="mi">1</span>         <span class="c1"># change object in-place</span>

<span class="n">args</span> <span class="o">=</span> <span class="n">callByRef</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="s1">&#39;old-value&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
<span class="n">func4</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>几乎没有任何适当理由将问题如此复杂化。</p>
</li>
</ol>
<p>你的最佳选择是返回一个包含多个结果的元组。</p>
</div>
<div class="section" id="how-do-you-make-a-higher-order-function-in-python">
<h3><a class="toc-backref" href="#id19">如何在Python中创建高阶函数？</a><a class="headerlink" href="#how-do-you-make-a-higher-order-function-in-python" title="永久链接至标题">¶</a></h3>
<p>你有两种选择：使用嵌套作用域，或者使用可调用对象。 例如，假设你想要定义 <code class="docutils literal notranslate"><span class="pre">linear(a,b)</span></code> 使其返回一个函数 <code class="docutils literal notranslate"><span class="pre">f(x)</span></code> 来设计 <code class="docutils literal notranslate"><span class="pre">a*x+b</span></code> 的值。 可以使用以下嵌套作用域:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">linear</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">result</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="n">b</span>
    <span class="k">return</span> <span class="n">result</span>
</pre></div>
</div>
<p>或使用一个可调用对象:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">linear</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span>

    <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span>
</pre></div>
</div>
<p>在两种情况下，:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">taxes</span> <span class="o">=</span> <span class="n">linear</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<p>都会给出一个可调用对象，使得 <code class="docutils literal notranslate"><span class="pre">taxes(10e6)</span> <span class="pre">==</span> <span class="pre">0.3</span> <span class="pre">*</span> <span class="pre">10e6</span> <span class="pre">+</span> <span class="pre">2</span></code>.</p>
<p>可调用对象方式的缺点是速度略慢且生成的代码略长。 但是，请注意一组可调用对象能够通过继承来共享签名:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">exponential</span><span class="p">(</span><span class="n">linear</span><span class="p">):</span>
    <span class="c1"># __init__ inherited</span>
    <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">**</span> <span class="bp">self</span><span class="o">.</span><span class="n">b</span><span class="p">)</span>
</pre></div>
</div>
<p>对象可以封装多个方法的状态:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">counter</span><span class="p">:</span>

    <span class="n">value</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">x</span>

    <span class="k">def</span> <span class="nf">up</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">down</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">-</span> <span class="mi">1</span>

<span class="n">count</span> <span class="o">=</span> <span class="n">counter</span><span class="p">()</span>
<span class="n">inc</span><span class="p">,</span> <span class="n">dec</span><span class="p">,</span> <span class="n">reset</span> <span class="o">=</span> <span class="n">count</span><span class="o">.</span><span class="n">up</span><span class="p">,</span> <span class="n">count</span><span class="o">.</span><span class="n">down</span><span class="p">,</span> <span class="n">count</span><span class="o">.</span><span class="n">set</span>
</pre></div>
</div>
<p>这里 <code class="docutils literal notranslate"><span class="pre">inc()</span></code>, <code class="docutils literal notranslate"><span class="pre">dec()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">reset()</span></code> 将表现为共享同一计数变量的多个函数。</p>
</div>
<div class="section" id="how-do-i-copy-an-object-in-python">
<h3><a class="toc-backref" href="#id20">如何在Python中复制对象？</a><a class="headerlink" href="#how-do-i-copy-an-object-in-python" title="永久链接至标题">¶</a></h3>
<p>一般来说，通常情况下请尝试 <a class="reference internal" href="../library/copy.html#copy.copy" title="copy.copy"><code class="xref py py-func docutils literal notranslate"><span class="pre">copy.copy()</span></code></a> 或 <a class="reference internal" href="../library/copy.html#copy.deepcopy" title="copy.deepcopy"><code class="xref py py-func docutils literal notranslate"><span class="pre">copy.deepcopy()</span></code></a>。 不是所有对象都可以复制，但多数都是可以的。</p>
<p>某些对象可以方便地复制。 例如字典具有 <a class="reference internal" href="../library/stdtypes.html#dict.copy" title="dict.copy"><code class="xref py py-meth docutils literal notranslate"><span class="pre">copy()</span></code></a> 方法:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">newdict</span> <span class="o">=</span> <span class="n">olddict</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</pre></div>
</div>
<p>序列可以通过切片来复制:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">new_l</span> <span class="o">=</span> <span class="n">l</span><span class="p">[:]</span>
</pre></div>
</div>
</div>
<div class="section" id="how-can-i-find-the-methods-or-attributes-of-an-object">
<h3><a class="toc-backref" href="#id21">如何找到对象的方法或属性？</a><a class="headerlink" href="#how-can-i-find-the-methods-or-attributes-of-an-object" title="永久链接至标题">¶</a></h3>
<p>对于一个用户自定义类的实例 x，<code class="docutils literal notranslate"><span class="pre">dir(x)</span></code> 将返回一个按字母顺序排序的包含实例属性和方法及其类所定义的属性名称的列表。</p>
</div>
<div class="section" id="how-can-my-code-discover-the-name-of-an-object">
<h3><a class="toc-backref" href="#id22">我的代码如何才能发现对象的名称？</a><a class="headerlink" href="#how-can-my-code-discover-the-name-of-an-object" title="永久链接至标题">¶</a></h3>
<p>通常来说是做不到的，因为对象并不真正具有名称。 在本质上，赋值总是会将一个名称绑定到某个值；<code class="docutils literal notranslate"><span class="pre">def</span></code> 和 <code class="docutils literal notranslate"><span class="pre">class</span></code> 语句也是如此，但在这种情况下该值是一个可调用对象。 考虑以下代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
<span class="gp">... </span>    <span class="k">pass</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">B</span> <span class="o">=</span> <span class="n">A</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">B</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="n">a</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="go">&lt;__main__.A object at 0x16D07CC&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">&lt;__main__.A object at 0x16D07CC&gt;</span>
</pre></div>
</div>
<p>不严谨地讲，该类有一个名称：虽然它是绑定了两个名称并通过名称 B 发起调用，所创建的实例仍然被视为类 A 的一个实例。 但是实例的名称则无法确定地说是 a 或是 b，因为有两个名称被绑定到了同一个值。</p>
<p>一般来说你的代码应该没有必要“知道”特定值的名称。 除非你是在编写特殊的内省程序，出现这样的问题通常表明如果改变方式可能会更有利。</p>
<p>在 comp.lang.python 中，Fredrik Lundh 在回答这样的问题时曾经给出过一个绝佳的类比：</p>
<blockquote>
<div><p>跟你找出在你家门廊见到的某只猫的名字所用的办法一样：猫（对象）自己无法告诉你它的名字，它根本就不在乎 —— 所以找出它叫什么名字的唯一办法是问你的所有邻居（命名空间）那是不是他们的猫（对象）……</p>
<p>……并且如果你发现它有很多名字或根本没有名字也不必觉得惊讶！</p>
</div></blockquote>
</div>
<div class="section" id="what-s-up-with-the-comma-operator-s-precedence">
<h3><a class="toc-backref" href="#id23">逗号运算符的优先级是什么？</a><a class="headerlink" href="#what-s-up-with-the-comma-operator-s-precedence" title="永久链接至标题">¶</a></h3>
<p>逗号在 Python 中不是运算符。 考虑这个例子:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s2">&quot;a&quot;</span> <span class="ow">in</span> <span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="s2">&quot;a&quot;</span>
<span class="go">(False, &#39;a&#39;)</span>
</pre></div>
</div>
<p>由于逗号不是运算符而是表达式之间的分隔符，以上代码的含义就相当于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="s2">&quot;a&quot;</span> <span class="ow">in</span> <span class="s2">&quot;b&quot;</span><span class="p">),</span> <span class="s2">&quot;a&quot;</span>
</pre></div>
</div>
<p>而不是:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="s2">&quot;a&quot;</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="s2">&quot;a&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>对于各种赋值运算符 (<code class="docutils literal notranslate"><span class="pre">=</span></code>, <code class="docutils literal notranslate"><span class="pre">+=</span></code> 等) 来说同样如此。 它们并不是真正的运算符而是赋值语句中的语法分隔符。</p>
</div>
<div class="section" id="is-there-an-equivalent-of-c-s-ternary-operator">
<h3><a class="toc-backref" href="#id24">是否有与 C 的 &quot;?:&quot; 三目运算符等价的东西？</a><a class="headerlink" href="#is-there-an-equivalent-of-c-s-ternary-operator" title="永久链接至标题">¶</a></h3>
<p>有的。 相应语法如下:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">on_true</span><span class="p">]</span> <span class="k">if</span> <span class="p">[</span><span class="n">expression</span><span class="p">]</span> <span class="k">else</span> <span class="p">[</span><span class="n">on_false</span><span class="p">]</span>

<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">25</span>
<span class="n">small</span> <span class="o">=</span> <span class="n">x</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="k">else</span> <span class="n">y</span>
</pre></div>
</div>
<p>在 Python 2.5 引入此语法之前，常见的做法是使用逻辑运算符:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">expression</span><span class="p">]</span> <span class="ow">and</span> <span class="p">[</span><span class="n">on_true</span><span class="p">]</span> <span class="ow">or</span> <span class="p">[</span><span class="n">on_false</span><span class="p">]</span>
</pre></div>
</div>
<p>然而这种做法并不保险，因为当 <em>on_true</em> 具有布尔假值时将会给出错误的结果。 所以，使用 <code class="docutils literal notranslate"><span class="pre">...</span> <span class="pre">if</span> <span class="pre">...</span> <span class="pre">else</span> <span class="pre">...</span></code> 形式总是会更好。</p>
</div>
<div class="section" id="is-it-possible-to-write-obfuscated-one-liners-in-python">
<h3><a class="toc-backref" href="#id25">是否可以用Python编写混淆的单行程序?</a><a class="headerlink" href="#is-it-possible-to-write-obfuscated-one-liners-in-python" title="永久链接至标题">¶</a></h3>
<p>可以。通常是在 <a class="reference internal" href="../reference/expressions.html#lambda"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">lambda</span></code></a> 中嵌套 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">lambda</span></code> 来实现的。请参阅以下三个来自 Ulf Bartelt 的示例代码：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">reduce</span>

<span class="c1"># Primes &lt; 1000</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">y</span><span class="p">:</span><span class="n">y</span><span class="o">*</span><span class="n">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span><span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">!=</span><span class="mi">0</span><span class="p">,</span>
<span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="o">=</span><span class="n">y</span><span class="p">:</span><span class="n">y</span><span class="o">%</span><span class="n">x</span><span class="p">,</span><span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="nb">int</span><span class="p">(</span><span class="nb">pow</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="mf">0.5</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">))),</span><span class="mi">1</span><span class="p">),</span><span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">1000</span><span class="p">)))))</span>

<span class="c1"># First 10 Fibonacci numbers</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">f</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">f</span><span class="p">:(</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">f</span><span class="p">)</span><span class="o">+</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="n">f</span><span class="p">))</span> <span class="k">if</span> <span class="n">x</span><span class="o">&gt;</span><span class="mi">1</span> <span class="k">else</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">f</span><span class="p">),</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))))</span>

<span class="c1"># Mandelbrot set</span>
<span class="nb">print</span><span class="p">((</span><span class="k">lambda</span> <span class="n">Ru</span><span class="p">,</span><span class="n">Ro</span><span class="p">,</span><span class="n">Iu</span><span class="p">,</span><span class="n">Io</span><span class="p">,</span><span class="n">IM</span><span class="p">,</span><span class="n">Sx</span><span class="p">,</span><span class="n">Sy</span><span class="p">:</span><span class="n">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span><span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="p">,</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">y</span><span class="p">,</span>
<span class="n">Iu</span><span class="o">=</span><span class="n">Iu</span><span class="p">,</span><span class="n">Io</span><span class="o">=</span><span class="n">Io</span><span class="p">,</span><span class="n">Ru</span><span class="o">=</span><span class="n">Ru</span><span class="p">,</span><span class="n">Ro</span><span class="o">=</span><span class="n">Ro</span><span class="p">,</span><span class="n">Sy</span><span class="o">=</span><span class="n">Sy</span><span class="p">,</span><span class="n">L</span><span class="o">=</span><span class="k">lambda</span> <span class="n">yc</span><span class="p">,</span><span class="n">Iu</span><span class="o">=</span><span class="n">Iu</span><span class="p">,</span><span class="n">Io</span><span class="o">=</span><span class="n">Io</span><span class="p">,</span><span class="n">Ru</span><span class="o">=</span><span class="n">Ru</span><span class="p">,</span><span class="n">Ro</span><span class="o">=</span><span class="n">Ro</span><span class="p">,</span><span class="n">i</span><span class="o">=</span><span class="n">IM</span><span class="p">,</span>
<span class="n">Sx</span><span class="o">=</span><span class="n">Sx</span><span class="p">,</span><span class="n">Sy</span><span class="o">=</span><span class="n">Sy</span><span class="p">:</span><span class="n">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span><span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="p">,</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">xc</span><span class="o">=</span><span class="n">Ru</span><span class="p">,</span><span class="n">yc</span><span class="o">=</span><span class="n">yc</span><span class="p">,</span><span class="n">Ru</span><span class="o">=</span><span class="n">Ru</span><span class="p">,</span><span class="n">Ro</span><span class="o">=</span><span class="n">Ro</span><span class="p">,</span>
<span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">,</span><span class="n">Sx</span><span class="o">=</span><span class="n">Sx</span><span class="p">,</span><span class="n">F</span><span class="o">=</span><span class="k">lambda</span> <span class="n">xc</span><span class="p">,</span><span class="n">yc</span><span class="p">,</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">k</span><span class="p">,</span><span class="n">f</span><span class="o">=</span><span class="k">lambda</span> <span class="n">xc</span><span class="p">,</span><span class="n">yc</span><span class="p">,</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">k</span><span class="p">,</span><span class="n">f</span><span class="p">:(</span><span class="n">k</span><span class="o">&lt;=</span><span class="mi">0</span><span class="p">)</span><span class="ow">or</span> <span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="o">*</span><span class="n">y</span>
<span class="o">&gt;=</span><span class="mf">4.0</span><span class="p">)</span> <span class="ow">or</span> <span class="mi">1</span><span class="o">+</span><span class="n">f</span><span class="p">(</span><span class="n">xc</span><span class="p">,</span><span class="n">yc</span><span class="p">,</span><span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">-</span><span class="n">y</span><span class="o">*</span><span class="n">y</span><span class="o">+</span><span class="n">xc</span><span class="p">,</span><span class="mf">2.0</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="o">+</span><span class="n">yc</span><span class="p">,</span><span class="n">k</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">f</span><span class="p">):</span><span class="n">f</span><span class="p">(</span><span class="n">xc</span><span class="p">,</span><span class="n">yc</span><span class="p">,</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">,</span><span class="n">k</span><span class="p">,</span><span class="n">f</span><span class="p">):</span><span class="nb">chr</span><span class="p">(</span>
<span class="mi">64</span><span class="o">+</span><span class="n">F</span><span class="p">(</span><span class="n">Ru</span><span class="o">+</span><span class="n">x</span><span class="o">*</span><span class="p">(</span><span class="n">Ro</span><span class="o">-</span><span class="n">Ru</span><span class="p">)</span><span class="o">/</span><span class="n">Sx</span><span class="p">,</span><span class="n">yc</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">i</span><span class="p">)),</span><span class="nb">range</span><span class="p">(</span><span class="n">Sx</span><span class="p">))):</span><span class="n">L</span><span class="p">(</span><span class="n">Iu</span><span class="o">+</span><span class="n">y</span><span class="o">*</span><span class="p">(</span><span class="n">Io</span><span class="o">-</span><span class="n">Iu</span><span class="p">)</span><span class="o">/</span><span class="n">Sy</span><span class="p">),</span><span class="nb">range</span><span class="p">(</span><span class="n">Sy</span>
<span class="p">))))(</span><span class="o">-</span><span class="mf">2.1</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.2</span><span class="p">,</span> <span class="mf">1.2</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="mi">24</span><span class="p">))</span>
<span class="c1">#    \___ ___/  \___ ___/  |   |   |__ lines on screen</span>
<span class="c1">#        V          V      |   |______ columns on screen</span>
<span class="c1">#        |          |      |__________ maximum of &quot;iterations&quot;</span>
<span class="c1">#        |          |_________________ range on y axis</span>
<span class="c1">#        |____________________________ range on x axis</span>
</pre></div>
</div>
<p>请不要在家里尝试，骚年！</p>
</div>
<div class="section" id="what-does-the-slash-in-the-parameter-list-of-a-function-mean">
<span id="faq-positional-only-arguments"></span><h3><a class="toc-backref" href="#id26">函数参数列表中的斜杠（/）是什么意思？</a><a class="headerlink" href="#what-does-the-slash-in-the-parameter-list-of-a-function-mean" title="永久链接至标题">¶</a></h3>
<p>函数参数列表中的斜杠表示在它之前的形参是仅限位置形参。 仅限位置形参没有外部可用的名称。 在调用接受仅限位置形参的函数时，参数只会基于它们的位置被映射到形参。 例如，<a class="reference internal" href="../library/functions.html#pow" title="pow"><code class="xref py py-func docutils literal notranslate"><span class="pre">pow()</span></code></a> 是一个接受仅限位置形参的函数。 它的文档是这样的:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">help</span><span class="p">(</span><span class="nb">pow</span><span class="p">)</span>
<span class="go">Help on built-in function pow in module builtins:</span>

<span class="go">pow(x, y, z=None, /)</span>
<span class="go">   Equivalent to x**y (with two arguments) or x**y % z (with three arguments)</span>

<span class="go">   Some types, such as ints, are able to use a more efficient algorithm when</span>
<span class="go">   invoked using the three argument form.</span>
</pre></div>
</div>
<p>在形参列表末尾的斜杠意味着所有三个形参都是仅限位置形参。 因此，附带关键字参数调用 <a class="reference internal" href="../library/functions.html#pow" title="pow"><code class="xref py py-func docutils literal notranslate"><span class="pre">pow()</span></code></a> 将会导致报错:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">pow</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
  File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">pow() takes no keyword arguments</span>
</pre></div>
</div>
<p>请注意目前此特性只记录于文档而不是有效的 Python 语法，不过已经有 <span class="target" id="index-10"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-0570"><strong>PEP 570</strong></a> 提出了 Python 中使用仅位置形参的语法。</p>
</div>
</div>
<div class="section" id="numbers-and-strings">
<h2><a class="toc-backref" href="#id27">数字和字符串</a><a class="headerlink" href="#numbers-and-strings" title="永久链接至标题">¶</a></h2>
<div class="section" id="how-do-i-specify-hexadecimal-and-octal-integers">
<h3><a class="toc-backref" href="#id28">如何指定十六进制和八进制整数？</a><a class="headerlink" href="#how-do-i-specify-hexadecimal-and-octal-integers" title="永久链接至标题">¶</a></h3>
<p>要指定一个八进制数码，则在八进制值之前加一个零和一个小写或大写字母 &quot;o&quot; 作为前缀。 例如，要将变量 &quot;a&quot; 设为八进制的 &quot;10&quot; (十进制的 8)，就输入:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="mo">0o10</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span>
<span class="go">8</span>
</pre></div>
</div>
<p>十六进制数也同样简单。 只要在十六进制数之前加一个零和一个小写或大写字母 &quot;x&quot;。 十六进制数码中的字母可以为大写或小写。 例如在 Python 解释器中输入:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="mh">0xa5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span>
<span class="go">165</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span> <span class="o">=</span> <span class="mh">0XB2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b</span>
<span class="go">178</span>
</pre></div>
</div>
</div>
<div class="section" id="why-does-22-10-return-3">
<h3><a class="toc-backref" href="#id29">为什么-22 // 10返回-3？</a><a class="headerlink" href="#why-does-22-10-return-3" title="永久链接至标题">¶</a></h3>
<p>这主要是为了让 <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">%</span> <span class="pre">j</span></code> 的正负与 <code class="docutils literal notranslate"><span class="pre">j</span></code> 一致，如果你想要这样的结果，并且又想要:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">==</span> <span class="p">(</span><span class="n">i</span> <span class="o">//</span> <span class="n">j</span><span class="p">)</span> <span class="o">*</span> <span class="n">j</span> <span class="o">+</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="n">j</span><span class="p">)</span>
</pre></div>
</div>
<p>那么整除就必须向下取整。 C 同样要求保持一致，并且编译器在截短 <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">//</span> <span class="pre">j</span></code> 的结果值时需要使 <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">%</span> <span class="pre">j</span></code> 的正负与 <code class="docutils literal notranslate"><span class="pre">i</span></code> 一致。</p>
<p>对于 <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">%</span> <span class="pre">j</span></code> 来说 <code class="docutils literal notranslate"><span class="pre">j</span></code> 为负值的应用场景实际上是非常少的。 而 <code class="docutils literal notranslate"><span class="pre">j</span></code> 为正值的情况则非常多，并且实际上在所有情况下让 <code class="docutils literal notranslate"><span class="pre">i</span> <span class="pre">%</span> <span class="pre">j</span></code> 的结果为 <code class="docutils literal notranslate"><span class="pre">&gt;=</span> <span class="pre">0</span></code> 会更有用处。 如果如果现在时间为 10 时，那么 200 小时前应是几时？ <code class="docutils literal notranslate"><span class="pre">-190</span> <span class="pre">%</span> <span class="pre">12</span> <span class="pre">==</span> <span class="pre">2</span></code> 是有用处的；<code class="docutils literal notranslate"><span class="pre">-190</span> <span class="pre">%</span> <span class="pre">12</span> <span class="pre">==</span> <span class="pre">-10</span></code> 则是会导致意外的漏洞。</p>
</div>
<div class="section" id="how-do-i-convert-a-string-to-a-number">
<h3><a class="toc-backref" href="#id30">如何将字符串转换为数字？</a><a class="headerlink" href="#how-do-i-convert-a-string-to-a-number" title="永久链接至标题">¶</a></h3>
<p>对于整数，可使用内置的 <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-func docutils literal notranslate"><span class="pre">int()</span></code></a> 类型构造器，例如 <code class="docutils literal notranslate"><span class="pre">int('144')</span> <span class="pre">==</span> <span class="pre">144</span></code>。 类似地，可使用 <a class="reference internal" href="../library/functions.html#float" title="float"><code class="xref py py-func docutils literal notranslate"><span class="pre">float()</span></code></a> 转换为浮点数，例如 <code class="docutils literal notranslate"><span class="pre">float('144')</span> <span class="pre">==</span> <span class="pre">144.0</span></code>。</p>
<p>默认情况下，这些操作会将数字按十进制来解读，因此 <code class="docutils literal notranslate"><span class="pre">int('0144')</span> <span class="pre">==</span> <span class="pre">144</span></code> 而 <code class="docutils literal notranslate"><span class="pre">int('0x144')</span></code> 会引发 <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a>。 <code class="docutils literal notranslate"><span class="pre">int(string,</span> <span class="pre">base)</span></code> 接受第二个可选参数指定转换的基数，例如 <code class="docutils literal notranslate"><span class="pre">int('0x144',</span> <span class="pre">16)</span> <span class="pre">==</span> <span class="pre">324</span></code>。 如果指定基数为 0，则按 Python 规则解读数字：前缀 '0o' 表示八进制，而 '0x' 表示十六进制。</p>
<p>如果你只是想将字符串转为数字，请不要使用内置函数 <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>。 <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> 的速度会慢很多并且有安全风险：别人可能会传入具有你不想要的附带效果的 Python 表达式。 例如，别人可以传入 <code class="docutils literal notranslate"><span class="pre">__import__('os').system(&quot;rm</span> <span class="pre">-rf</span> <span class="pre">$HOME&quot;)</span></code> 这将删除你的家目录。</p>
<p><a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> 还具有将数字解读为 Python 表达式的效果，这样 <code class="docutils literal notranslate"><span class="pre">eval('09')</span></code> 将会导致语法错误，因为 Python 不允许十进制数的首位是 '0' ('0' 除外)。</p>
</div>
<div class="section" id="how-do-i-convert-a-number-to-a-string">
<h3><a class="toc-backref" href="#id31">如何将数字转换为字符串？</a><a class="headerlink" href="#how-do-i-convert-a-number-to-a-string" title="永久链接至标题">¶</a></h3>
<p>例如要将数字 144 转换为字符串 '144'，可使用内置类型构造器 <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-func docutils literal notranslate"><span class="pre">str()</span></code></a>。 如果想要表示为十六进制或八进制数，可使用内置函数 <a class="reference internal" href="../library/functions.html#hex" title="hex"><code class="xref py py-func docutils literal notranslate"><span class="pre">hex()</span></code></a> 或 <a class="reference internal" href="../library/functions.html#oct" title="oct"><code class="xref py py-func docutils literal notranslate"><span class="pre">oct()</span></code></a>。 想要更好地格式化，请参阅 <a class="reference internal" href="../reference/lexical_analysis.html#f-strings"><span class="std std-ref">格式化字符串字面值</span></a> 和 <a class="reference internal" href="../library/string.html#formatstrings"><span class="std std-ref">格式字符串语法</span></a> 等小节，例如 <code class="docutils literal notranslate"><span class="pre">&quot;{:04d}&quot;.format(144)</span></code> 生成 <code class="docutils literal notranslate"><span class="pre">'0144'</span></code> 而 <code class="docutils literal notranslate"><span class="pre">&quot;{:.3f}&quot;.format(1.0/3.0)</span></code> 生成 <code class="docutils literal notranslate"><span class="pre">'0.333'</span></code>。</p>
</div>
<div class="section" id="how-do-i-modify-a-string-in-place">
<h3><a class="toc-backref" href="#id32">如何修改字符串？</a><a class="headerlink" href="#how-do-i-modify-a-string-in-place" title="永久链接至标题">¶</a></h3>
<p>无法修改，因为字符串是不可变对象。 在大多数情况下，你应该使用你想要的各种部分来构造一个新字符串。 但是，如果你想要一个可以原地修改 Unicode 数据的对象，可尝试使用 <a class="reference internal" href="../library/io.html#io.StringIO" title="io.StringIO"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.StringIO</span></code></a> 对象或 <a class="reference internal" href="../library/array.html#module-array" title="array: Space efficient arrays of uniformly typed numeric values."><code class="xref py py-mod docutils literal notranslate"><span class="pre">array</span></code></a> 模块:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">io</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="s2">&quot;Hello, world&quot;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sio</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">StringIO</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sio</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
<span class="go">&#39;Hello, world&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sio</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>
<span class="go">7</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sio</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">&quot;there!&quot;</span><span class="p">)</span>
<span class="go">6</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sio</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
<span class="go">&#39;Hello, there!&#39;</span>

<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">array</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="s1">&#39;u&#39;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">array(&#39;u&#39;, &#39;Hello, world&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;y&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">array(&#39;u&#39;, &#39;yello, world&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="o">.</span><span class="n">tounicode</span><span class="p">()</span>
<span class="go">&#39;yello, world&#39;</span>
</pre></div>
</div>
</div>
<div class="section" id="how-do-i-use-strings-to-call-functions-methods">
<h3><a class="toc-backref" href="#id33">如何使用字符串调用函数/方法？</a><a class="headerlink" href="#how-do-i-use-strings-to-call-functions-methods" title="永久链接至标题">¶</a></h3>
<p>有多种技巧可供选择。</p>
<ul>
<li><p>最好的做法是使用一个将字符串映射到函数的字典。 这一技巧的主要优势在于字符串不必与函数名称一致。 这也是用于模拟其他语言中 case 结构的主要技巧:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">a</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="k">def</span> <span class="nf">b</span><span class="p">():</span>
    <span class="k">pass</span>

<span class="n">dispatch</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;go&#39;</span><span class="p">:</span> <span class="n">a</span><span class="p">,</span> <span class="s1">&#39;stop&#39;</span><span class="p">:</span> <span class="n">b</span><span class="p">}</span>  <span class="c1"># Note lack of parens for funcs</span>

<span class="n">dispatch</span><span class="p">[</span><span class="n">get_input</span><span class="p">()]()</span>  <span class="c1"># Note trailing parens to call function</span>
</pre></div>
</div>
</li>
<li><p>使用内置函数 <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a></p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">foo</span>
<span class="nb">getattr</span><span class="p">(</span><span class="n">foo</span><span class="p">,</span> <span class="s1">&#39;bar&#39;</span><span class="p">)()</span>
</pre></div>
</div>
<p>请注意 <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> 可用于任何对象，包括类、类实例、模块等等。</p>
<p>在标准库中多次使用了这个技巧，例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Foo</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">do_foo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="o">...</span>

    <span class="k">def</span> <span class="nf">do_bar</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="o">...</span>

<span class="n">f</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">foo_instance</span><span class="p">,</span> <span class="s1">&#39;do_&#39;</span> <span class="o">+</span> <span class="n">opname</span><span class="p">)</span>
<span class="n">f</span><span class="p">()</span>
</pre></div>
</div>
</li>
<li><p>使用 <a class="reference internal" href="../library/functions.html#locals" title="locals"><code class="xref py py-func docutils literal notranslate"><span class="pre">locals()</span></code></a> 或 <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> 来解析出函数名:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">myFunc</span><span class="p">():</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">)</span>

<span class="n">fname</span> <span class="o">=</span> <span class="s2">&quot;myFunc&quot;</span>

<span class="n">f</span> <span class="o">=</span> <span class="nb">locals</span><span class="p">()[</span><span class="n">fname</span><span class="p">]</span>
<span class="n">f</span><span class="p">()</span>

<span class="n">f</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span>
<span class="n">f</span><span class="p">()</span>
</pre></div>
</div>
<p>注意：使用 <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> 速度慢而且危险。 如果你不能绝对掌控字符串的内容，别人将能传入可被解析为任意函数直接执行的字符串。</p>
</li>
</ul>
</div>
<div class="section" id="is-there-an-equivalent-to-perl-s-chomp-for-removing-trailing-newlines-from-strings">
<h3><a class="toc-backref" href="#id34">是否有与Perl 的chomp() 等效的方法，用于从字符串中删除尾随换行符？</a><a class="headerlink" href="#is-there-an-equivalent-to-perl-s-chomp-for-removing-trailing-newlines-from-strings" title="永久链接至标题">¶</a></h3>
<p>可以使用 <code class="docutils literal notranslate"><span class="pre">S.rstrip(&quot;\r\n&quot;)</span></code> 从字符串 <code class="docutils literal notranslate"><span class="pre">S</span></code> 的末尾删除所有的换行符，而不删除其他尾随空格。如果字符串 <code class="docutils literal notranslate"><span class="pre">S</span></code> 表示多行，且末尾有几个空行，则将删除所有空行的换行符：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">lines</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;line 1 </span><span class="se">\r\n</span><span class="s2">&quot;</span>
<span class="gp">... </span>         <span class="s2">&quot;</span><span class="se">\r\n</span><span class="s2">&quot;</span>
<span class="gp">... </span>         <span class="s2">&quot;</span><span class="se">\r\n</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">lines</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n\r</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="go">&#39;line 1 &#39;</span>
</pre></div>
</div>
<p>由于通常只在一次读取一行文本时才需要这样做，所以使用 <code class="docutils literal notranslate"><span class="pre">S.rstrip()</span></code> 这种方式工作得很好。</p>
</div>
<div class="section" id="is-there-a-scanf-or-sscanf-equivalent">
<h3><a class="toc-backref" href="#id35">是否有 scanf() 或 sscanf() 的对应物？</a><a class="headerlink" href="#is-there-a-scanf-or-sscanf-equivalent" title="永久链接至标题">¶</a></h3>
<p>没有这样的对应物。</p>
<p>对于简单的输入解析，最方便的做法通常是使用字符串对象的 <a class="reference internal" href="../library/stdtypes.html#str.split" title="str.split"><code class="xref py py-meth docutils literal notranslate"><span class="pre">split()</span></code></a> 方法将一行内容拆解为以空格分隔的单词，然后使用 <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-func docutils literal notranslate"><span class="pre">int()</span></code></a> 或 <a class="reference internal" href="../library/functions.html#float" title="float"><code class="xref py py-func docutils literal notranslate"><span class="pre">float()</span></code></a> 将表示十进制数的字符串转换为数值。 <code class="docutils literal notranslate"><span class="pre">split()</span></code> 支持可选的 &quot;sep&quot; 形参，适用于内容行使用空格符以外的分隔符的情况。</p>
<p>以于更复杂的输入解析，正则表达式会比 C 的 <code class="xref c c-func docutils literal notranslate"><span class="pre">sscanf()</span></code> 更强大，也更适合此类任务。</p>
</div>
<div class="section" id="what-does-unicodedecodeerror-or-unicodeencodeerror-error-mean">
<h3><a class="toc-backref" href="#id36">'UnicodeDecodeError' 或 'UnicodeEncodeError' 错误是什么意思？</a><a class="headerlink" href="#what-does-unicodedecodeerror-or-unicodeencodeerror-error-mean" title="永久链接至标题">¶</a></h3>
<p>见 <a class="reference internal" href="../howto/unicode.html#unicode-howto"><span class="std std-ref">Unicode 指南</span></a></p>
</div>
</div>
<div class="section" id="performance">
<h2><a class="toc-backref" href="#id37">性能</a><a class="headerlink" href="#performance" title="永久链接至标题">¶</a></h2>
<div class="section" id="my-program-is-too-slow-how-do-i-speed-it-up">
<h3><a class="toc-backref" href="#id38">我的程序太慢了。该如何加快速度？</a><a class="headerlink" href="#my-program-is-too-slow-how-do-i-speed-it-up" title="永久链接至标题">¶</a></h3>
<p>总的来说，这是个棘手的问题。首先，下面列出了深入了解前需要记住的事情：</p>
<ul class="simple">
<li><p>不同的 Python 实现具有不同的性能特点。 本 FAQ 着重解答的是 <a class="reference internal" href="../glossary.html#term-cpython"><span class="xref std std-term">CPython</span></a>。</p></li>
<li><p>行为可能因操作系统而异，尤其是在谈论 I / O 或多线程时。</p></li>
<li><p>在尝试优化任何代码 <em>前</em> ，应始终找到程序中的热点（请参阅 <a class="reference internal" href="../library/profile.html#module-profile" title="profile: Python source profiler."><code class="xref py py-mod docutils literal notranslate"><span class="pre">profile</span></code></a> 模块）。</p></li>
<li><p>编写基准脚本将允许您在搜索改进时快速迭代（请参阅 <a class="reference internal" href="../library/timeit.html#module-timeit" title="timeit: Measure the execution time of small code snippets."><code class="xref py py-mod docutils literal notranslate"><span class="pre">timeit</span></code></a> 模块）。</p></li>
<li><p>强烈建议在可能引入隐藏在复杂优化中的回归之前，要有良好的代码覆盖率（通过单元测试或任何其他技术）。</p></li>
</ul>
<p>话虽如此，加速Python代码有很多技巧。以下是一些可以达到可接受的性能水平的一般原则：</p>
<ul class="simple">
<li><p>使您的算法更快（或更改为更快的算法）可以产生比尝试在代码中使用微优化技巧更大的好处。</p></li>
<li><p>使用正确的数据结构。参考文档 <a class="reference internal" href="../library/stdtypes.html#bltin-types"><span class="std std-ref">内置类型</span></a> 和 <a class="reference internal" href="../library/collections.html#module-collections" title="collections: Container datatypes"><code class="xref py py-mod docutils literal notranslate"><span class="pre">collections</span></code></a> 模块。</p></li>
<li><p>当标准库提供用于执行某些操作的原语时，可能（尽管不能保证）比您可能提出的任何替代方案更快。对于用C编写的原语，例如内置函数和一些扩展类型，这是真的。例如，请确保使用 <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> 内置方法或相关的 <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> 函数进行排序（有关适度高级用法的示例，请参阅 <a class="reference internal" href="../howto/sorting.html#sortinghowto"><span class="std std-ref">排序指南</span></a> ）。</p></li>
<li><p>抽象倾向于创造间接性并迫使翻译更多地工作。如果间接级别超过完成的有用工作量，则程序将变慢。你应该避免过度抽象，特别是在微小的功能或方法的形式下（这通常也会对可读性产生不利影响）。</p></li>
</ul>
<p>如果你已经达到纯 Python 允许的限制，那么有一些工具可以让你走得更远。 例如， <a class="reference external" href="http://cython.org">Cython</a> 可以将稍微修改的 Python 代码版本编译为 C 扩展，并且可以在许多不同的平台上使用。 Cython 可以利用编译（和可选的类型注释）来使代码明显快于解释运行时的速度。 如果您对 C 编程技能有信心，也可以自己 <a class="reference internal" href="../extending/index.html#extending-index"><span class="std std-ref">编写 C 扩展模块</span></a> 。</p>
<div class="admonition seealso">
<p class="admonition-title">参见</p>
<p>专门介绍 <a class="reference external" href="https://wiki.python.org/moin/PythonSpeed/PerformanceTips">性能提示</a> 的wiki页面。</p>
</div>
</div>
<div class="section" id="what-is-the-most-efficient-way-to-concatenate-many-strings-together">
<span id="efficient-string-concatenation"></span><h3><a class="toc-backref" href="#id39">将多个字符串连接在一起的最有效方法是什么？</a><a class="headerlink" href="#what-is-the-most-efficient-way-to-concatenate-many-strings-together" title="永久链接至标题">¶</a></h3>
<p><a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> 和 <a class="reference internal" href="../library/stdtypes.html#bytes" title="bytes"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a> 对象是不可变的，因此将多个字符串连接在一起效率很低，因为每个连接都会创建一个新对象。在一般情况下，总运行时间是总字符串长度的二次方。</p>
<p>要连接多个 <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> 对象，通常推荐的用法是将它们放入一个列表中并在结尾处调用 <a class="reference internal" href="../library/stdtypes.html#str.join" title="str.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">str.join()</span></code></a> ：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">chunks</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">my_strings</span><span class="p">:</span>
    <span class="n">chunks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">chunks</span><span class="p">)</span>
</pre></div>
</div>
<p>（另一个合理有效的惯用方法是 <a class="reference internal" href="../library/io.html#io.StringIO" title="io.StringIO"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.StringIO</span></code></a> ）</p>
<p>要连接多个 <a class="reference internal" href="../library/stdtypes.html#str" title="str"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a> 对象，建议使用本地连接（ <code class="docutils literal notranslate"><span class="pre">+=</span></code> 运算符）扩展 <a class="reference internal" href="../library/stdtypes.html#bytearray" title="bytearray"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytearray</span></code></a> 对象：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">()</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">my_bytes_objects</span><span class="p">:</span>
    <span class="n">result</span> <span class="o">+=</span> <span class="n">b</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="sequences-tuples-lists">
<h2><a class="toc-backref" href="#id40">序列（元组/列表）</a><a class="headerlink" href="#sequences-tuples-lists" title="永久链接至标题">¶</a></h2>
<div class="section" id="how-do-i-convert-between-tuples-and-lists">
<h3><a class="toc-backref" href="#id41">如何在元组和列表之间进行转换？</a><a class="headerlink" href="#how-do-i-convert-between-tuples-and-lists" title="永久链接至标题">¶</a></h3>
<p>类型构造器 <code class="docutils literal notranslate"><span class="pre">tuple(seq)</span></code> 可将任意序列（实际上是任意可迭代对象）转换为具有相同排列顺序的相同条目的元组。</p>
<p>例如，<code class="docutils literal notranslate"><span class="pre">tuple([1,</span> <span class="pre">2,</span> <span class="pre">3])</span></code> 产生 <code class="docutils literal notranslate"><span class="pre">(1,</span> <span class="pre">2,</span> <span class="pre">3)</span></code> 而 <code class="docutils literal notranslate"><span class="pre">tuple('abc')</span></code> 产生 <code class="docutils literal notranslate"><span class="pre">('a',</span> <span class="pre">'b',</span> <span class="pre">'c')</span></code>。 如果参数为一个元组，它不会创建副本而是返回同一对象，因此如果你不确定某个对象是否为元组时也可简单地调用 <a class="reference internal" href="../library/stdtypes.html#tuple" title="tuple"><code class="xref py py-func docutils literal notranslate"><span class="pre">tuple()</span></code></a>。</p>
<p>类型构造器 <code class="docutils literal notranslate"><span class="pre">list(seq)</span></code> 可将任意序列或可迭代对象转换为具有相同排列顺序的相同条目的列表。 例如，<code class="docutils literal notranslate"><span class="pre">list((1,</span> <span class="pre">2,</span> <span class="pre">3))</span></code> 产生 <code class="docutils literal notranslate"><span class="pre">[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code> 而 <code class="docutils literal notranslate"><span class="pre">list('abc')</span></code> 产生 <code class="docutils literal notranslate"><span class="pre">['a',</span> <span class="pre">'b',</span> <span class="pre">'c']</span></code>。 如果参数为一个列表，它会像 <code class="docutils literal notranslate"><span class="pre">seq[:]</span></code> 那样创建一个副本。</p>
</div>
<div class="section" id="what-s-a-negative-index">
<h3><a class="toc-backref" href="#id42">什么是负数序号？</a><a class="headerlink" href="#what-s-a-negative-index" title="永久链接至标题">¶</a></h3>
<p>Python 序列使用正数或负数作为序号或称索引号。 对于正数序号，第一个序号为 0 而 1 为第二个序号，依此类推。 对于负数序号，倒数第一个序号为 -1 而倒数第二个序号为 -2，依此类推。 可以认为 <code class="docutils literal notranslate"><span class="pre">seq[-n]</span></code> 就相当于 <code class="docutils literal notranslate"><span class="pre">seq[len(seq)-n]</span></code>。</p>
<p>使用负数序号有时会很方便。 例如 <code class="docutils literal notranslate"><span class="pre">S[:-1]</span></code> 就是原字符串去掉最后一个字符，这可以用来移除某个字符串末尾的换行符。</p>
</div>
<div class="section" id="how-do-i-iterate-over-a-sequence-in-reverse-order">
<h3><a class="toc-backref" href="#id43">如何以相反的顺序迭代序列？</a><a class="headerlink" href="#how-do-i-iterate-over-a-sequence-in-reverse-order" title="永久链接至标题">¶</a></h3>
<p>使用 <a class="reference internal" href="../library/functions.html#reversed" title="reversed"><code class="xref py py-func docutils literal notranslate"><span class="pre">reversed()</span></code></a> 内置函数，这是Python 2.4中的新功能:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">sequence</span><span class="p">):</span>
    <span class="o">...</span>  <span class="c1"># do something with x ...</span>
</pre></div>
</div>
<p>这不会修改您的原始序列，而是构建一个反向顺序的新副本以进行迭代。</p>
<p>在 Python 2.3 里，您可以使用扩展切片语法:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sequence</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
    <span class="o">...</span>  <span class="c1"># do something with x ...</span>
</pre></div>
</div>
</div>
<div class="section" id="how-do-you-remove-duplicates-from-a-list">
<h3><a class="toc-backref" href="#id44">如何从列表中删除重复项？</a><a class="headerlink" href="#how-do-you-remove-duplicates-from-a-list" title="永久链接至标题">¶</a></h3>
<p>有关执行此操作的许多方法的详细讨论，请参阅 Python Cookbook:</p>
<blockquote>
<div><p><a class="reference external" href="https://code.activestate.com/recipes/52560/">https://code.activestate.com/recipes/52560/</a></p>
</div></blockquote>
<p>如果您不介意重新排序列表，请对其进行排序，然后从列表末尾进行扫描，删除重复项：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">mylist</span><span class="p">:</span>
    <span class="n">mylist</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
    <span class="n">last</span> <span class="o">=</span> <span class="n">mylist</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">mylist</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">last</span> <span class="o">==</span> <span class="n">mylist</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="k">del</span> <span class="n">mylist</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">last</span> <span class="o">=</span> <span class="n">mylist</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</pre></div>
</div>
<p>如果列表的所有元素都可以用作设置键（即：它们都是 <a class="reference internal" href="../glossary.html#term-hashable"><span class="xref std std-term">hashable</span></a> ），这通常会更快:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">mylist</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">mylist</span><span class="p">))</span>
</pre></div>
</div>
<p>这会将列表转换为集合，从而删除重复项，然后返回到列表中。</p>
</div>
<div class="section" id="how-do-you-make-an-array-in-python">
<h3><a class="toc-backref" href="#id45">如何在Python中创建数组？</a><a class="headerlink" href="#how-do-you-make-an-array-in-python" title="永久链接至标题">¶</a></h3>
<p>使用列表:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">&quot;is&quot;</span><span class="p">,</span> <span class="s2">&quot;an&quot;</span><span class="p">,</span> <span class="s2">&quot;array&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>列表在时间复杂度方面相当于C或Pascal数组；主要区别在于，python列表可以包含许多不同类型的对象。</p>
<p><code class="docutils literal notranslate"><span class="pre">array</span></code> 模块还提供了创建具有紧凑表示的固定类型的数组的方法，但它的索引速度比列表慢。还要注意，数字扩展和其他扩展还定义了具有各种特性的类似数组的结构。</p>
<p>要获取Lisp样式的列表，可以使用元组模拟cons单元：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">lisp_list</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;like&quot;</span><span class="p">,</span>  <span class="p">(</span><span class="s2">&quot;this&quot;</span><span class="p">,</span>  <span class="p">(</span><span class="s2">&quot;example&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="p">)</span> <span class="p">)</span>
</pre></div>
</div>
<p>如果需要可变性，可以使用列表而不是元组。这里模拟lisp car的是 <code class="docutils literal notranslate"><span class="pre">lisp_list[0]</span></code> ，模拟cdr的是 <code class="docutils literal notranslate"><span class="pre">lisp_list[1]</span></code> 。只有在你确定真的需要的时候才这样做，因为它通常比使用Python列表慢得多。</p>
</div>
<div class="section" id="how-do-i-create-a-multidimensional-list">
<span id="faq-multidimensional-list"></span><h3><a class="toc-backref" href="#id46">如何创建多维列表？</a><a class="headerlink" href="#how-do-i-create-a-multidimensional-list" title="永久链接至标题">¶</a></h3>
<p>你可能试图制作一个像这样的多维数组:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">A</span> <span class="o">=</span> <span class="p">[[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="mi">3</span>
</pre></div>
</div>
<p>如果你打印它，看起来是正确的：</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">A</span>
<span class="go">[[None, None], [None, None], [None, None]]</span>
</pre></div>
</div>
<p>但是，当你给某一项赋值时，会同时在多个位置显示变化：</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">A</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">A</span>
<span class="go">[[5, None], [5, None], [5, None]]</span>
</pre></div>
</div>
<p>其中的原因在于使用 <code class="docutils literal notranslate"><span class="pre">*</span></code> 对列表执行重复操作并不是创建副本，它只是创建现有对象的引用。 <code class="docutils literal notranslate"><span class="pre">*3</span></code> 创建了对长度为二的同一列表的 3 个引用。 对某一行的改变会作用于所有行，通常这一定不是你所希望的。</p>
<p>建议的做法是先创建一个所需长度的列表，然后其中的元素再以一个新创建的列表来填充:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">A</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="mi">3</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
    <span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="mi">2</span>
</pre></div>
</div>
<p>这样就生成了一个包含 3 个长度为二的不同列表的列表。 你也可以使用列表推导式:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span>
<span class="n">A</span> <span class="o">=</span> <span class="p">[[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="n">w</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">)]</span>
</pre></div>
</div>
<p>或者你还可以使用提供矩阵类型的扩展包；其中最著名的是 <a class="reference external" href="http://www.numpy.org/">NumPy</a>。</p>
</div>
<div class="section" id="how-do-i-apply-a-method-to-a-sequence-of-objects">
<h3><a class="toc-backref" href="#id47">如何将方法应用于一系列对象？</a><a class="headerlink" href="#how-do-i-apply-a-method-to-a-sequence-of-objects" title="永久链接至标题">¶</a></h3>
<p>可以使用列表推导式：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">obj</span><span class="o">.</span><span class="n">method</span><span class="p">()</span> <span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="n">mylist</span><span class="p">]</span>
</pre></div>
</div>
</div>
<div class="section" id="why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works">
<span id="faq-augmented-assignment-tuple-error"></span><h3><a class="toc-backref" href="#id48">为什么 a_tuple[i] += ['item'] 会在执行加法时引发异常？</a><a class="headerlink" href="#why-does-a-tuple-i-item-raise-an-exception-when-the-addition-works" title="永久链接至标题">¶</a></h3>
<p>这是由两个事实共同导致的结果，一是增强赋值运算符属于 <em>赋值</em> 运算符，二是在 Python 中存在可变和不可变两种不同的对象。</p>
<p>此处的讨论在任何对元组中指向可变对象的元素使用增强赋值运算符的情况都是普遍成立的，但在此我们只以 <code class="docutils literal notranslate"><span class="pre">list</span></code> 和 <code class="docutils literal notranslate"><span class="pre">+=</span></code> 来举例。</p>
<p>如果你写成这样:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="gt">Traceback (most recent call last):</span>
   <span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">&#39;tuple&#39; object does not support item assignment</span>
</pre></div>
</div>
<p>发生异常的原因是显而易见的: <code class="docutils literal notranslate"><span class="pre">1</span></code> 会与对象 <code class="docutils literal notranslate"><span class="pre">a_tuple[0]</span></code> 相加，而该对象为 (<code class="docutils literal notranslate"><span class="pre">1</span></code>)，得到结果对象 <code class="docutils literal notranslate"><span class="pre">2</span></code>，但当我们试图将运算结果 <code class="docutils literal notranslate"><span class="pre">2</span></code> 赋值给元组的 <code class="docutils literal notranslate"><span class="pre">0</span></code> 号元素时就将报错，因为我们不能改变元组的元素所指向的对象。</p>
<p>在表层之处，以上增强赋值语句所做的大致是这样:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">result</span>
<span class="gt">Traceback (most recent call last):</span>
  <span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">&#39;tuple&#39; object does not support item assignment</span>
</pre></div>
</div>
<p>由于元组是不可变的，因此操作的赋值部分会引发错误。</p>
<p>当你这样写的时候:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span> <span class="o">=</span> <span class="p">([</span><span class="s1">&#39;foo&#39;</span><span class="p">],</span> <span class="s1">&#39;bar&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+=</span> <span class="p">[</span><span class="s1">&#39;item&#39;</span><span class="p">]</span>
<span class="gt">Traceback (most recent call last):</span>
  <span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">&#39;tuple&#39; object does not support item assignment</span>
</pre></div>
</div>
<p>发生异常会令人略感吃惊，还有一个更为令人吃惊的事实：虽然有报错，但是添加操作却生效了:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="go">[&#39;foo&#39;, &#39;item&#39;]</span>
</pre></div>
</div>
<p>要明白为何会这样，你需要知道 (a) 如果一个对象实现了 <code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> 魔术方法，它会在执行 <code class="docutils literal notranslate"><span class="pre">+=</span></code> 增强赋值时被调用，并且其返回值将用于该赋值语句； (b) 对于列表来说，<code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> 等价于在列表上调用 <code class="docutils literal notranslate"><span class="pre">extend</span></code> 并返回该列表。 因此对于列表我们可以说 <code class="docutils literal notranslate"><span class="pre">+=</span></code> 就是 <code class="docutils literal notranslate"><span class="pre">list.extend</span></code> 的“快捷方式”:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_list</span> <span class="o">+=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_list</span>
<span class="go">[1]</span>
</pre></div>
</div>
<p>这相当于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="n">a_list</span><span class="o">.</span><span class="fm">__iadd__</span><span class="p">([</span><span class="mi">1</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_list</span> <span class="o">=</span> <span class="n">result</span>
</pre></div>
</div>
<p>a_list 所引用的对象已被修改，而引用被修改对象的指针又重新被赋值给 <code class="docutils literal notranslate"><span class="pre">a_list</span></code>。 赋值的最终结果没有变化，因为它是引用 <code class="docutils literal notranslate"><span class="pre">a_list</span></code> 之前所引用的同一对象的指针，但仍然发生了赋值操作。</p>
<p>因此，在我们的元组示例中，发生的事情等同于：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="fm">__iadd__</span><span class="p">([</span><span class="s1">&#39;item&#39;</span><span class="p">])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a_tuple</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">result</span>
<span class="gt">Traceback (most recent call last):</span>
  <span class="c">...</span>
<span class="gr">TypeError</span>: <span class="n">&#39;tuple&#39; object does not support item assignment</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">__iadd__</span></code> 成功执行，因此列表得到了扩充，但是虽然 <code class="docutils literal notranslate"><span class="pre">result</span></code> 指向了 <code class="docutils literal notranslate"><span class="pre">a_tuple[0]</span></code> 已经指向的同一对象，最后的赋值仍然导致了报错，因为元组是不可变的。</p>
</div>
<div class="section" id="i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python">
<h3><a class="toc-backref" href="#id49">我想做一个复杂的排序：你能用Python做一个Schwartzian变换吗？</a><a class="headerlink" href="#i-want-to-do-a-complicated-sort-can-you-do-a-schwartzian-transform-in-python" title="永久链接至标题">¶</a></h3>
<p>该技术归功于Perl社区的 Randal Schwartz，它通过将每个元素映射到其 &quot;排序值（sort value）&quot; 的度量对列表中的元素进行排序。在Python中，使用 <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> 方法的 <code class="docutils literal notranslate"><span class="pre">key</span></code> 参数：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">Isorted</span> <span class="o">=</span> <span class="n">L</span><span class="p">[:]</span>
<span class="n">Isorted</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="mi">10</span><span class="p">:</span><span class="mi">15</span><span class="p">]))</span>
</pre></div>
</div>
</div>
<div class="section" id="how-can-i-sort-one-list-by-values-from-another-list">
<h3><a class="toc-backref" href="#id50">如何按其他列表中的值对一个列表进行排序？</a><a class="headerlink" href="#how-can-i-sort-one-list-by-values-from-another-list" title="永久链接至标题">¶</a></h3>
<p>将它们合并到元组的迭代器中，对结果列表进行排序，然后选择所需的元素。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">list1</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;what&quot;</span><span class="p">,</span> <span class="s2">&quot;I&#39;m&quot;</span><span class="p">,</span> <span class="s2">&quot;sorting&quot;</span><span class="p">,</span> <span class="s2">&quot;by&quot;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">list2</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;something&quot;</span><span class="p">,</span> <span class="s2">&quot;else&quot;</span><span class="p">,</span> <span class="s2">&quot;to&quot;</span><span class="p">,</span> <span class="s2">&quot;sort&quot;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pairs</span> <span class="o">=</span> <span class="nb">zip</span><span class="p">(</span><span class="n">list1</span><span class="p">,</span> <span class="n">list2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pairs</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">pairs</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">pairs</span>
<span class="go">[(&quot;I&#39;m&quot;, &#39;else&#39;), (&#39;by&#39;, &#39;sort&#39;), (&#39;sorting&#39;, &#39;to&#39;), (&#39;what&#39;, &#39;something&#39;)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">pairs</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">result</span>
<span class="go">[&#39;else&#39;, &#39;sort&#39;, &#39;to&#39;, &#39;something&#39;]</span>
</pre></div>
</div>
<p>最后一步的替代方案是:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pairs</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>
</div>
<p>如果你觉得这个更容易读懂，那么你可能更喜欢使用这个而不是前面的列表推导。然而，对于长列表来说，它的速度几乎是原来的两倍。为什么？首先， <code class="docutils literal notranslate"><span class="pre">append()</span></code> 操作必须重新分配内存，虽然它使用了一些技巧来避免每次都这样做，但它仍然偶尔需要这样做，而且代价相当高。第二，表达式 &quot;result.append&quot; 需要额外的属性查找。第三，必须执行所有这些函数调用会降低速度。</p>
</div>
</div>
<div class="section" id="objects">
<h2><a class="toc-backref" href="#id51">对象</a><a class="headerlink" href="#objects" title="永久链接至标题">¶</a></h2>
<div class="section" id="what-is-a-class">
<h3><a class="toc-backref" href="#id52">什么是类？</a><a class="headerlink" href="#what-is-a-class" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">类</span></code> 是通过执行类语句创建的特定对象类型。<code class="docutils literal notranslate"><span class="pre">类对象</span></code> 被当作模板来创建实例对象，实例对象包含了特定于数据类型的数据（属性）和代码（方法）。</p>
<p>类可以基于一个或多个的其他类，称之为基类（ES），它继承基类的属性和方法，这样就可以通过继承来连续地细化对象模型。例如：您可能有一个 <code class="docutils literal notranslate"><span class="pre">Mailbox</span></code> 类提供邮箱的基本访问方法.，它的子类 <code class="docutils literal notranslate"><span class="pre">MboxMailbox</span></code>, <code class="docutils literal notranslate"><span class="pre">MaildirMailbox</span></code>, <code class="docutils literal notranslate"><span class="pre">OutlookMailbox</span></code> 用于处理各种特定邮箱格式。</p>
</div>
<div class="section" id="what-is-a-method">
<h3><a class="toc-backref" href="#id53">什么是方法？</a><a class="headerlink" href="#what-is-a-method" title="永久链接至标题">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">方法</span></code> 实际上就是类定义中的函数。对于某个对象 <code class="docutils literal notranslate"><span class="pre">x</span></code> 上的方法，通常称为 <code class="docutils literal notranslate"><span class="pre">x.name(arguments...)</span></code> 。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">arg</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">attribute</span>
</pre></div>
</div>
</div>
<div class="section" id="what-is-self">
<h3><a class="toc-backref" href="#id54">什么是 self ？</a><a class="headerlink" href="#what-is-self" title="永久链接至标题">¶</a></h3>
<p>Self 只是 <code class="docutils literal notranslate"><span class="pre">方法</span></code> 的第一个参数的常规名称。例如：对于某个类的某个实例 <code class="docutils literal notranslate"><span class="pre">x</span></code> ，其方法 <code class="docutils literal notranslate"><span class="pre">meth(self,</span> <span class="pre">a,</span> <span class="pre">b,</span> <span class="pre">c)</span></code> 实际上应该被称为 <code class="docutils literal notranslate"><span class="pre">x.meth(a,</span> <span class="pre">b,</span> <span class="pre">c)</span></code> ；对于被调用的方法会被称为 <code class="docutils literal notranslate"><span class="pre">meth(x,</span> <span class="pre">a,</span> <span class="pre">b,</span> <span class="pre">c)</span></code> 。</p>
<p>另请参阅 <a class="reference internal" href="design.html#why-self"><span class="std std-ref">为什么必须在方法定义和调用中显式使用“self”？</span></a> 。</p>
</div>
<div class="section" id="how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it">
<h3><a class="toc-backref" href="#id55">如何检查对象是否为给定类或其子类的一个实例？</a><a class="headerlink" href="#how-do-i-check-if-an-object-is-an-instance-of-a-given-class-or-of-a-subclass-of-it" title="永久链接至标题">¶</a></h3>
<p>可使用内置函数 <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">cls)</span></code>。 你可以提供一个元组而不是单个类来检查某个对象是否为任意多个类当中某一个类的实例，例如 <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">(class1,</span> <span class="pre">class2,</span> <span class="pre">...))</span></code>，也可以检查某个对象是否为 Python 内置类型当中某一个类型的对象，例如 <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">str)</span></code> 或 <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">(int,</span> <span class="pre">float,</span> <span class="pre">complex))</span></code>。</p>
<p>请注意大多数程序不会经常对用户自定义类使用 <a class="reference internal" href="../library/functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a>。 如果是你自已开发的类，更正确的面向对象风格是在类中定义方法来封装特定的行为，而不是检查对象的类并根据它属于什么类来做不同的事。 例如，如果你有一个执行某些操作的函数:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">Mailbox</span><span class="p">):</span>
        <span class="o">...</span>  <span class="c1"># code to search a mailbox</span>
    <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">Document</span><span class="p">):</span>
        <span class="o">...</span>  <span class="c1"># code to search a document</span>
    <span class="k">elif</span> <span class="o">...</span>
</pre></div>
</div>
<p>更好的方法是在所有类上定义一个 <code class="docutils literal notranslate"><span class="pre">search()</span></code> 方法，然后调用它：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Mailbox</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="o">...</span>  <span class="c1"># code to search a mailbox</span>

<span class="k">class</span> <span class="nc">Document</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="o">...</span>  <span class="c1"># code to search a document</span>

<span class="n">obj</span><span class="o">.</span><span class="n">search</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="what-is-delegation">
<h3><a class="toc-backref" href="#id56">什么是委托？</a><a class="headerlink" href="#what-is-delegation" title="永久链接至标题">¶</a></h3>
<p>委托是一种面向对象的技巧（也称为设计模式）。 假设您有一个对象 <code class="docutils literal notranslate"><span class="pre">x</span></code> 并且想要改变其中一个方法的行为。 您可以创建一个新类，它提供您感兴趣的方法的新实现，并将所有其他方法委托给 <code class="docutils literal notranslate"><span class="pre">x</span></code> 的相应方法。</p>
<p>Python程序员可以轻松实现委托。 例如，以下类实现了一个类，该类的行为类似于文件，但将所有写入的数据转换为大写：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">UpperOut</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">outfile</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_outfile</span> <span class="o">=</span> <span class="n">outfile</span>

    <span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_outfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>

    <span class="k">def</span> <span class="fm">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_outfile</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
</pre></div>
</div>
<p>在这里 <code class="docutils literal notranslate"><span class="pre">UpperOut</span></code> 类重新定义了 <code class="docutils literal notranslate"><span class="pre">write()</span></code> 方法在调用下层的 <code class="docutils literal notranslate"><span class="pre">self._outfile.write()</span></code> 方法之前将参数字符串转换为大写形式。 所有其他方法都被委托给下层的 <code class="docutils literal notranslate"><span class="pre">self._outfile</span></code> 对象。 委托是通过 <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> 方法来完成的；请参阅 <a class="reference internal" href="../reference/datamodel.html#attribute-access"><span class="std std-ref">语言参考</span></a> 了解有关控制属性访问的更多信息。</p>
<p>请注意对于更一般的情况来说，委托可能包含更多细节问题。 当某些属性既需要读取又需要设置时，类还必须定义 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a> 方法，并且这样做必须小心谨慎。 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a> 的基本实现大致相当于以下代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">X</span><span class="p">:</span>
    <span class="o">...</span>
    <span class="k">def</span> <span class="fm">__setattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
    <span class="o">...</span>
</pre></div>
</div>
<p>大多数 <a class="reference internal" href="../reference/datamodel.html#object.__setattr__" title="object.__setattr__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__setattr__()</span></code></a> 实现必须修改 <code class="docutils literal notranslate"><span class="pre">self.__dict__</span></code> 来为自身保存局部状态而又不至于造成无限递归。</p>
</div>
<div class="section" id="how-do-i-call-a-method-defined-in-a-base-class-from-a-derived-class-that-overrides-it">
<h3><a class="toc-backref" href="#id57">如何从覆盖基类的派生类调用基类中定义的方法?</a><a class="headerlink" href="#how-do-i-call-a-method-defined-in-a-base-class-from-a-derived-class-that-overrides-it" title="永久链接至标题">¶</a></h3>
<p>使用内置的 <a class="reference internal" href="../library/functions.html#super" title="super"><code class="xref py py-func docutils literal notranslate"><span class="pre">super()</span></code></a> 函数：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">(</span><span class="n">Derived</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">meth</span><span class="p">()</span>
</pre></div>
</div>
<p>对于 Python 3.0之前的版本，您可能正在使用经典类：对于诸如 <code class="docutils literal notranslate"><span class="pre">class</span> <span class="pre">Derived(Base):</span> <span class="pre">...</span></code> 之类的类定义，可以将在 <code class="docutils literal notranslate"><span class="pre">Base</span></code> (或 <code class="docutils literal notranslate"><span class="pre">Base</span></code> 中的一个的基类）中定义的方法 <code class="docutils literal notranslate"><span class="pre">meth()</span></code> 调用为 <code class="docutils literal notranslate"><span class="pre">Base.meth(self,</span> <span class="pre">arguments...)</span></code> 。这里， <code class="docutils literal notranslate"><span class="pre">Base.meth</span></code> 是一个未绑定的方法，因此您需要提供 <code class="docutils literal notranslate"><span class="pre">self</span></code> 参数。</p>
</div>
<div class="section" id="how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class">
<h3><a class="toc-backref" href="#id58">如何组织代码以便更改基类？</a><a class="headerlink" href="#how-can-i-organize-my-code-to-make-it-easier-to-change-the-base-class" title="永久链接至标题">¶</a></h3>
<p>可以为基类定义别名，在类定义之前为其分配实际基类，并在整个类中使用别名。然后更改分配给别名的值，就能实现上述要求。顺便提一下，如果你想动态决定（例如，取决于资源的可用性）要使用哪个基类，这个技巧也很方便。例如：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">BaseAlias</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">real</span> <span class="n">base</span> <span class="n">class</span><span class="o">&gt;</span>

<span class="k">class</span> <span class="nc">Derived</span><span class="p">(</span><span class="n">BaseAlias</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">BaseAlias</span><span class="o">.</span><span class="n">meth</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="o">...</span>
</pre></div>
</div>
</div>
<div class="section" id="how-do-i-create-static-class-data-and-static-class-methods">
<h3><a class="toc-backref" href="#id59">如何创建静态类数据和静态类方法？</a><a class="headerlink" href="#how-do-i-create-static-class-data-and-static-class-methods" title="永久链接至标题">¶</a></h3>
<p>Python支持静态数据和静态方法（在C ++或Java的意义上）。</p>
<p>对于静态数据，只需定义一个类属性。要为属性分配新值，就必须在赋值中显式使用类名：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
    <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>   <span class="c1"># number of times C.__init__ called</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">C</span><span class="o">.</span><span class="n">count</span> <span class="o">=</span> <span class="n">C</span><span class="o">.</span><span class="n">count</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">getcount</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">C</span><span class="o">.</span><span class="n">count</span>  <span class="c1"># or return self.count</span>
</pre></div>
</div>
<p>对于任意 <code class="docutils literal notranslate"><span class="pre">c</span></code> 来说只要 <code class="docutils literal notranslate"><span class="pre">isinstance(c,</span> <span class="pre">C)</span></code> 为真，则 <code class="docutils literal notranslate"><span class="pre">c.count</span></code> 同样也指向 <code class="docutils literal notranslate"><span class="pre">C.count</span></code>，除非被 <code class="docutils literal notranslate"><span class="pre">c</span></code> 自身，或者从 <code class="docutils literal notranslate"><span class="pre">c.__class__</span></code> 回到 <code class="docutils literal notranslate"><span class="pre">C</span></code> 的基类搜索路径上的某个类所重载。</p>
<p>注意：在 C 的某个方法内部，像 <code class="docutils literal notranslate"><span class="pre">self.count</span> <span class="pre">=</span> <span class="pre">42</span></code> 这样的赋值将在 <code class="docutils literal notranslate"><span class="pre">self</span></code> 自身的字典中新建一个名为 &quot;count&quot; 的不相关实例。 想要重新绑定类静态数据名称就必须总是指明类名，无论是在方法内部还是外部:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">C</span><span class="o">.</span><span class="n">count</span> <span class="o">=</span> <span class="mi">314</span>
</pre></div>
</div>
<p>静态方法是可行的：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
    <span class="nd">@staticmethod</span>
    <span class="k">def</span> <span class="nf">static</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">,</span> <span class="n">arg3</span><span class="p">):</span>
        <span class="c1"># No &#39;self&#39; parameter!</span>
        <span class="o">...</span>
</pre></div>
</div>
<p>然而，获得静态方法效果的更直接的方法是通过一个简单的模块级函数：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">getcount</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">C</span><span class="o">.</span><span class="n">count</span>
</pre></div>
</div>
<p>如果您的代码是结构化的，以便为每个模块定义一个类（或紧密相关的类层次结构），那么这就提供了所需的封装。</p>
</div>
<div class="section" id="how-can-i-overload-constructors-or-methods-in-python">
<h3><a class="toc-backref" href="#id60">如何在Python中重载构造函数（或方法）？</a><a class="headerlink" href="#how-can-i-overload-constructors-or-methods-in-python" title="永久链接至标题">¶</a></h3>
<p>这个答案实际上适用于所有方法，但问题通常首先出现在构造函数的上下文中。</p>
<p>在C ++中，你会这样写</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">class</span> <span class="n">C</span> <span class="p">{</span>
    <span class="n">C</span><span class="p">()</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;No arguments</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span> <span class="p">}</span>
    <span class="n">C</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Argument is &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>在Python中，您必须编写一个构造函数，使用默认参数捕获所有情况。例如：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;No arguments&quot;</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Argument is&quot;</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
</pre></div>
</div>
<p>这不完全等同，但在实践中足够接近。</p>
<p>你也可以尝试一个可变长度的参数列表，例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
    <span class="o">...</span>
</pre></div>
</div>
<p>相同的方法适用于所有方法定义。</p>
</div>
<div class="section" id="i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam">
<h3><a class="toc-backref" href="#id61">我尝试使用 __spam ，但是得到一个关于 _SomeClassName__spam 的错误信息。</a><a class="headerlink" href="#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam" title="永久链接至标题">¶</a></h3>
<p>以双下划线打头的变量会被“更名”以提供一种定义类私有变量的简单而有效的方式。 任何形式为 <code class="docutils literal notranslate"><span class="pre">__spam</span></code> 的标识符（至少前缀两个下划线，至多后缀一个下划线）文本会被替换为 <code class="docutils literal notranslate"><span class="pre">_classname__spam</span></code>，其中 <code class="docutils literal notranslate"><span class="pre">classname</span></code> 为去除了全部前缀下划线的当前类名称。</p>
<p>这并不能保证私密性：外部用户仍然可以访问 &quot;_classname__spam&quot; 属性，私有变量值也在对象的 <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> 中可见。 许多 Python 程序员从来都不使用这种私有变量名称。</p>
</div>
<div class="section" id="my-class-defines-del-but-it-is-not-called-when-i-delete-the-object">
<h3><a class="toc-backref" href="#id62">类定义了 __del__ 方法，但是删除对象时没有调用它。</a><a class="headerlink" href="#my-class-defines-del-but-it-is-not-called-when-i-delete-the-object" title="永久链接至标题">¶</a></h3>
<p>这有几个可能的原因。</p>
<p>del 语句不一定调用 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> —— 它只是减少对象的引用计数，如果（引用计数）达到零，才会调用 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a>。</p>
<p>如果数据结构包含循环链接（例如，每个子级都有一个父级引用，每个父级都有一个子级列表的树），则引用计数将永远不会返回零。尽管Python 偶尔会运行一个算法来检测这样的循环，但在数据结构的引用计数清零后，垃圾收集器可能需要一段时间来运行，因此 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> 方法可能会在不方便和随机的时间被调用。这对于重现一个问题，是非常不方便的。更糟糕的是，对象 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> 的方法执行顺序是任意的。虽然可以运行 <a class="reference internal" href="../library/gc.html#gc.collect" title="gc.collect"><code class="xref py py-func docutils literal notranslate"><span class="pre">gc.collect()</span></code></a> 来强制回收，但在一些病态的情况下，对象永远不会被回收。</p>
<p>尽管有循环收集器，但在对象上定义一个显式的 <code class="docutils literal notranslate"><span class="pre">close()</span></code> 方法以便在用完之后调用它仍然是一个好主意。 这样 <code class="docutils literal notranslate"><span class="pre">close()</span></code> 方法可以随即删除引用子对象的属性。 不要直接调用 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> —— 应该由 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> 调用 <code class="docutils literal notranslate"><span class="pre">close()</span></code>，并且 <code class="docutils literal notranslate"><span class="pre">close()</span></code> 能确保可以被同一对象多次地调用。</p>
<p>另一种避免循环引用的方法是使用 <a class="reference internal" href="../library/weakref.html#module-weakref" title="weakref: Support for weak references and weak dictionaries."><code class="xref py py-mod docutils literal notranslate"><span class="pre">weakref</span></code></a> 模块，该模块允许您指向对象而不增加其引用计数。例如，树状数据结构应该对其父级和同级引用使用弱引用（如果需要的话！）</p>
<p>最后，如果 <a class="reference internal" href="../reference/datamodel.html#object.__del__" title="object.__del__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__del__()</span></code></a> 方法引发异常，会将警告消息打印到 <a class="reference internal" href="../library/sys.html#sys.stderr" title="sys.stderr"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a> 。</p>
</div>
<div class="section" id="how-do-i-get-a-list-of-all-instances-of-a-given-class">
<h3><a class="toc-backref" href="#id63">如何获取给定类的所有实例的列表？</a><a class="headerlink" href="#how-do-i-get-a-list-of-all-instances-of-a-given-class" title="永久链接至标题">¶</a></h3>
<p>Python不跟踪类（或内置类型）的所有实例。您可以对类的构造函数进行编程，以通过保留每个实例的弱引用列表来跟踪所有实例。</p>
</div>
<div class="section" id="why-does-the-result-of-id-appear-to-be-not-unique">
<h3><a class="toc-backref" href="#id64">为什么 <code class="docutils literal notranslate"><span class="pre">id()</span></code> 的结果看起来不是唯一的？</a><a class="headerlink" href="#why-does-the-result-of-id-appear-to-be-not-unique" title="永久链接至标题">¶</a></h3>
<p><a class="reference internal" href="../library/functions.html#id" title="id"><code class="xref py py-func docutils literal notranslate"><span class="pre">id()</span></code></a> 返回一个整数，该整数在对象的生命周期内保证是唯一的。因为在CPython中，这是对象的内存地址，所以经常发生在从内存中删除对象之后，下一个新创建的对象被分配在内存中的相同位置。这个例子说明了这一点：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">id</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> 
<span class="go">13901272</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">id</span><span class="p">(</span><span class="mi">2000</span><span class="p">)</span> 
<span class="go">13901272</span>
</pre></div>
</div>
<p>这两个id属于之前创建的不同整数对象，并在执行 <code class="docutils literal notranslate"><span class="pre">id()</span></code> 调用后立即删除。要确保要检查其id的对象仍处于活动状态，请创建对该对象的另一个引用：</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2000</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> 
<span class="go">13901272</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">id</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> 
<span class="go">13891296</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="modules">
<h2><a class="toc-backref" href="#id65">模块</a><a class="headerlink" href="#modules" title="永久链接至标题">¶</a></h2>
<div class="section" id="how-do-i-create-a-pyc-file">
<h3><a class="toc-backref" href="#id66">如何创建 .pyc 文件？</a><a class="headerlink" href="#how-do-i-create-a-pyc-file" title="永久链接至标题">¶</a></h3>
<p>当一个模块首次被导入时（或自当前已编译文件创建后源文件被修改时），将会在对应 <code class="docutils literal notranslate"><span class="pre">.py</span></code> 文件所在目录的 <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> 子目录下创建一个包含已编译代码的 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件。 该 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件的文件名的开头部分将与对应 <code class="docutils literal notranslate"><span class="pre">.py</span></code> 文件名相同，并以 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 为后缀，中间部门则是基于创建它的特定 <code class="docutils literal notranslate"><span class="pre">python</span></code> 二进制代码版本。 （详情参见 <span class="target" id="index-11"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-3147"><strong>PEP 3147</strong></a>。）</p>
<p>无法创建 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件的可能原因是包含源文件的目录存在权限问题，这意味着 <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> 子目录无法被创建。 举例来说，如果你以某一用户来开发程序但以另一用户身份来运行程序时就可能发生问题，测试 Web 服务器就属于这种情况。</p>
<p>除非设置了 <span class="target" id="index-12"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONDONTWRITEBYTECODE</span></code></a> 环境变量，否则当你导入模块并且 Python 具有创建 <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> 子目录并将已编译模块写入该子目录的能力（权限、存储空间等等）时就会自动创建 .pyc 文件。</p>
<p>在最高层级运行的 Python 脚本不被视为导入，因此不会创建 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件。 例如，如果你有一个最高层级模块文件 <code class="docutils literal notranslate"><span class="pre">foo.py</span></code>，它又导入了另一个模块 <code class="docutils literal notranslate"><span class="pre">xyz.py</span></code>，当你运行 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 模块 (通过输入终端命令 <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">foo.py</span></code>)，则将为 <code class="docutils literal notranslate"><span class="pre">xyz</span></code> 创建一个 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code>，因为 <code class="docutils literal notranslate"><span class="pre">xyz</span></code> 是被导入的，但不会为 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 创建 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件，因为 <code class="docutils literal notranslate"><span class="pre">foo.py</span></code> 不是被导入的。</p>
<p>如果你需要为 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 创建 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件 —— 即为不是被导入的模块创建 <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件 —— 你可以使用 <a class="reference internal" href="../library/py_compile.html#module-py_compile" title="py_compile: Generate byte-code files from Python source files."><code class="xref py py-mod docutils literal notranslate"><span class="pre">py_compile</span></code></a> 和 <a class="reference internal" href="../library/compileall.html#module-compileall" title="compileall: Tools for byte-compiling all Python source files in a directory tree."><code class="xref py py-mod docutils literal notranslate"><span class="pre">compileall</span></code></a> 模块。</p>
<p><a class="reference internal" href="../library/py_compile.html#module-py_compile" title="py_compile: Generate byte-code files from Python source files."><code class="xref py py-mod docutils literal notranslate"><span class="pre">py_compile</span></code></a> 模块能够手动编译任意模块。 一种做法是交互式地使用该模块中的 <code class="docutils literal notranslate"><span class="pre">compile()</span></code> 函数:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">py_compile</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">py_compile</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;foo.py&#39;</span><span class="p">)</span>                 
</pre></div>
</div>
<p>这将会将  <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件写入与 <code class="docutils literal notranslate"><span class="pre">foo.py</span></code> 相同位置下的 <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> 子目录（或者你也可以通过可选参数 <code class="docutils literal notranslate"><span class="pre">cfile</span></code> 来重载该行为）。</p>
<p>你还可以使用 <a class="reference internal" href="../library/compileall.html#module-compileall" title="compileall: Tools for byte-compiling all Python source files in a directory tree."><code class="xref py py-mod docutils literal notranslate"><span class="pre">compileall</span></code></a> 模块自动编译一个目录或多个目录下的所有文件。 具体做法可以是在命令行提示符中运行 <code class="docutils literal notranslate"><span class="pre">compileall.py</span></code> 并提供包含要编译 Python 文件的目录路径:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">compileall</span> <span class="o">.</span>
</pre></div>
</div>
</div>
<div class="section" id="how-do-i-find-the-current-module-name">
<h3><a class="toc-backref" href="#id67">如何找到当前模块名称？</a><a class="headerlink" href="#how-do-i-find-the-current-module-name" title="永久链接至标题">¶</a></h3>
<p>模块可以通过查看预定义的全局变量 <code class="docutils literal notranslate"><span class="pre">__name__</span></code> 找到自己的模块名称。如果它的值为 <code class="docutils literal notranslate"><span class="pre">'__main__'</span></code> ，程序将作为脚本运行。通常，通过导入使用的许多模块也提供命令行界面或自检，并且只在检查 <code class="docutils literal notranslate"><span class="pre">__name__</span></code> 之后，才执行之后的代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Running test...&#39;</span><span class="p">)</span>
    <span class="o">...</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="how-can-i-have-modules-that-mutually-import-each-other">
<h3><a class="toc-backref" href="#id68">如何让模块相互导入？</a><a class="headerlink" href="#how-can-i-have-modules-that-mutually-import-each-other" title="永久链接至标题">¶</a></h3>
<p>假设您有以下模块：</p>
<p>foo.py:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">bar</span> <span class="kn">import</span> <span class="n">bar_var</span>
<span class="n">foo_var</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>bar.py:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">foo</span> <span class="kn">import</span> <span class="n">foo_var</span>
<span class="n">bar_var</span> <span class="o">=</span> <span class="mi">2</span>
</pre></div>
</div>
<p>问题是解释器将执行以下步骤：</p>
<ul class="simple">
<li><p>首先导入foo</p></li>
<li><p>创建用于foo的空全局变量</p></li>
<li><p>foo被编译并开始执行</p></li>
<li><p>foo 导入 bar</p></li>
<li><p>创建了用于bar 的空全局变量</p></li>
<li><p>bar被编译并开始执行</p></li>
<li><p>bar导入foo（这是一个空操作（no-op ），因为已经有一个名为foo的模块）</p></li>
<li><p>bar.foo_var = foo.foo_var</p></li>
</ul>
<p>最后一步失败了，因为Python还没有解释foo，而foo的全局符号字典仍然是空的。</p>
<p>当你使用 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">foo</span></code> ，然后尝试在全局代码中访问 <code class="docutils literal notranslate"><span class="pre">foo.foo_var</span></code> 时，会发生同样的事情。</p>
<p>这个问题有（至少）三种可能的解决方法。</p>
<p>Guido van Rossum 建议避免使用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">&lt;module&gt;</span> <span class="pre">import</span> <span class="pre">...</span></code> ，并将所有代码放在函数中。全局变量和类变量的初始化只能使用常量或内置函数。这意味着导入模块中的所有内容都被引用为 <code class="docutils literal notranslate"><span class="pre">&lt;module&gt;.&lt;name&gt;</span></code> 。</p>
<p>Jim Roskind建议在每个模块中按以下顺序执行步骤：</p>
<ul class="simple">
<li><p>导出（全局变量，函数和不需要导入基类的类）</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">导入</span></code> 声明</p></li>
<li><p>活动代码（包括从导入值初始化的全局变量）。</p></li>
</ul>
<p>van Rossum不喜欢这种方法，因为导入出现在一个陌生的地方，但这种方法确实有效。</p>
<p>Matthias Urlichs建议重构代码，以便首先不需要递归导入。</p>
<p>这些解决方案并不相互排斥。</p>
</div>
<div class="section" id="import-x-y-z-returns-module-x-how-do-i-get-z">
<h3><a class="toc-backref" href="#id69">__import__('x.y.z') 返回 &lt;module 'x'&gt;; 如何获取z?</a><a class="headerlink" href="#import-x-y-z-returns-module-x-how-do-i-get-z" title="永久链接至标题">¶</a></h3>
<p>考虑使用 <a class="reference internal" href="../library/importlib.html#module-importlib" title="importlib: The implementation of the import machinery."><code class="xref py py-mod docutils literal notranslate"><span class="pre">importlib</span></code></a> 中的函数 <a class="reference internal" href="../library/importlib.html#importlib.import_module" title="importlib.import_module"><code class="xref py py-func docutils literal notranslate"><span class="pre">import_module()</span></code></a> ：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">z</span> <span class="o">=</span> <span class="n">importlib</span><span class="o">.</span><span class="n">import_module</span><span class="p">(</span><span class="s1">&#39;x.y.z&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="when-i-edit-an-imported-module-and-reimport-it-the-changes-don-t-show-up-why-does-this-happen">
<h3><a class="toc-backref" href="#id70">当我编辑了导入过的模块并重新导入它时，这些变化没有显示出来。为什么会这样？</a><a class="headerlink" href="#when-i-edit-an-imported-module-and-reimport-it-the-changes-don-t-show-up-why-does-this-happen" title="永久链接至标题">¶</a></h3>
<p>出于效率和一致性的原因，Python仅在第一次导入模块时读取模块文件。如果不这么做，在一个由许多模块组成的程序中，每个模块都会导入相同的基本模块，那么基本模块将被解析和重新解析多次。要强制重新读取已更改的模块，请执行以下操作:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">importlib</span>
<span class="kn">import</span> <span class="nn">modname</span>
<span class="n">importlib</span><span class="o">.</span><span class="n">reload</span><span class="p">(</span><span class="n">modname</span><span class="p">)</span>
</pre></div>
</div>
<p>警告：这种技术不是100％万无一失。特别是包含如下语句的模块</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">modname</span> <span class="kn">import</span> <span class="n">some_objects</span>
</pre></div>
</div>
<p>将继续使用旧版本的导入对象。如果模块包含类定义，则不会更新现有的类实例以使用新的类定义。这可能导致以下矛盾行为:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">importlib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">cls</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">C</span><span class="p">()</span>                <span class="c1"># Create an instance of C</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">importlib</span><span class="o">.</span><span class="n">reload</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
<span class="go">&lt;module &#39;cls&#39; from &#39;cls.py&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="bp">cls</span><span class="o">.</span><span class="n">C</span><span class="p">)</span>       <span class="c1"># isinstance is false?!?</span>
<span class="go">False</span>
</pre></div>
</div>
<p>如果打印出类对象的“标识”，问题的本质就会明确：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">hex</span><span class="p">(</span><span class="nb">id</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="vm">__class__</span><span class="p">))</span>
<span class="go">&#39;0x7352a0&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">hex</span><span class="p">(</span><span class="nb">id</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">C</span><span class="p">))</span>
<span class="go">&#39;0x4198d0&#39;</span>
</pre></div>
</div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">目录</a></h3>
  <ul>
<li><a class="reference internal" href="#">编程常见问题</a><ul>
<li><a class="reference internal" href="#general-questions">一般问题</a></li>
<li><a class="reference internal" href="#core-language">核心语言</a></li>
<li><a class="reference internal" href="#numbers-and-strings">数字和字符串</a></li>
<li><a class="reference internal" href="#performance">性能</a></li>
<li><a class="reference internal" href="#sequences-tuples-lists">序列（元组/列表）</a></li>
<li><a class="reference internal" href="#objects">对象</a></li>
<li><a class="reference internal" href="#modules">模块</a></li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="general.html"
                        title="上一章">Python常见问题</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="design.html"
                        title="下一章">设计和历史常见问题</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">提交 Bug</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/3.7/Doc/faq/programming.rst"
            rel="nofollow">显示源代码
        </a>
      </li>
    </ul>
  </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="design.html" title="设计和历史常见问题"
             >下一页</a> |</li>
        <li class="right" >
          <a href="general.html" title="Python常见问题"
             >上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <a href="../index.html">3.7.8 Documentation</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Python 常见问题</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">版权所有</a> 2001-2020, Python Software Foundation.
    <br />
    Python 软件基金会是一个非盈利组织。
    <a href="https://www.python.org/psf/donations/">请捐助。</a>
    <br />
    最后更新于 6月 29, 2020.
    <a href="../bugs.html">发现了问题</a>？
    <br />
    使用<a href="http://sphinx.pocoo.org/">Sphinx</a>2.3.1 创建。
    </div>

  </body>
</html>